diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff95002..e89cc70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,25 @@ jobs: steps: - uses: actions/checkout@v6 + with: + persist-credentials: false + - uses: cachix/install-nix-action@9280e7aca88deada44c930f1e2c78e21c3ae3edd # v31.7.0 + with: + install_url: https://releases.nixos.org/nix/nix-2.31.2/install + github_access_token: "${{ secrets.GITHUB_TOKEN }}" + - name: Set Git credentials + run: | + git config --global 'url.https://api@github.com/'.insteadOf 'https://github.com/' + git config --global 'url.https://ssh@github.com/'.insteadOf 'ssh://git@github.com/' + git config --global 'url.https://git@github.com/'.insteadOf 'git@github.com:' + - uses: cachix/cachix-action@v17 + with: + name: veridise-public + authToken: '${{ secrets.CACHIX_PUBLIC_TOKEN }}' + - name: Set nix environment + uses: nicknovitski/nix-develop@v1 + env: + CI_BOT_PAT: "${{ secrets.CI_BUILD_TOKEN }}" - name: Cache cargo crates uses: actions/cache@v5 with: @@ -26,8 +45,10 @@ jobs: ~/.cargo/git target key: ${{ runner.os }}-${{ matrix.BUILD_TARGET }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - name: Run tests for `core` - run: cargo test --profile ${{ matrix.BUILD_TARGET }} --all-features -p haloumi-core + - name: Build in "${{ matrix.BUILD_TARGET }}" mode + run: cargo build --profile ${{ matrix.BUILD_TARGET }} --all-features + - name: Run tests in "${{ matrix.BUILD_TARGET }}" mode + run: cargo test --profile ${{ matrix.BUILD_TARGET }} --all-features doc-links: if: github.event.pull_request.draft == false @@ -36,8 +57,25 @@ jobs: steps: - uses: actions/checkout@v6 - - name: 'Install rust-toolchain.toml' - run: rustup toolchain install + with: + persist-credentials: false + - uses: cachix/install-nix-action@9280e7aca88deada44c930f1e2c78e21c3ae3edd # v31.7.0 + with: + install_url: https://releases.nixos.org/nix/nix-2.31.2/install + github_access_token: "${{ secrets.GITHUB_TOKEN }}" + - name: Set Git credentials + run: | + git config --global 'url.https://api@github.com/'.insteadOf 'https://github.com/' + git config --global 'url.https://ssh@github.com/'.insteadOf 'ssh://git@github.com/' + git config --global 'url.https://git@github.com/'.insteadOf 'git@github.com:' + - uses: cachix/cachix-action@v17 + with: + name: veridise-public + authToken: '${{ secrets.CACHIX_PUBLIC_TOKEN }}' + - name: Set nix environment + uses: nicknovitski/nix-develop@v1 + env: + CI_BOT_PAT: "${{ secrets.CI_BUILD_TOKEN }}" - name: cargo fetch run: cargo fetch @@ -59,15 +97,66 @@ jobs: clippy: if: github.event.pull_request.draft == false - name: Clippy + name: Run clippy timeout-minutes: 30 runs-on: ubuntu-latest + steps: - uses: actions/checkout@v6 - - name: 'Install rust-toolchain.toml' - run: rustup toolchain install + with: + persist-credentials: false + - uses: cachix/install-nix-action@9280e7aca88deada44c930f1e2c78e21c3ae3edd # v31.7.0 + with: + install_url: https://releases.nixos.org/nix/nix-2.31.2/install + github_access_token: "${{ secrets.GITHUB_TOKEN }}" + - name: Set Git credentials + run: | + git config --global 'url.https://api@github.com/'.insteadOf 'https://github.com/' + git config --global 'url.https://ssh@github.com/'.insteadOf 'ssh://git@github.com/' + git config --global 'url.https://git@github.com/'.insteadOf 'git@github.com:' + - uses: cachix/cachix-action@v17 + with: + name: veridise-public + authToken: '${{ secrets.CACHIX_PUBLIC_TOKEN }}' + - name: Set nix environment + uses: nicknovitski/nix-develop@v1 + env: + CI_BOT_PAT: "${{ secrets.CI_BUILD_TOKEN }}" + + - name: Run Clippy on `haloumi-core` + if: always() + run: cargo clippy -p haloumi-core --all-targets --all-features -- -Dwarnings --no-deps + + - name: Run Clippy on `haloumi-lowering` + if: always() + run: cargo clippy -p haloumi-lowering --all-targets --all-features -- -Dwarnings --no-deps + + - name: Run Clippy on `haloumi-ir` + if: always() + run: cargo clippy -p haloumi-ir --all-targets --all-features -- -Dwarnings --no-deps + + - name: Run Clippy on `haloumi-synthesis` + if: always() + run: cargo clippy -p haloumi-synthesis --all-targets --all-features -- -Dwarnings --no-deps + + - name: Run Clippy on `haloumi-ir-gen` + if: always() + run: cargo clippy -p haloumi-ir-gen --all-targets --all-features -- -Dwarnings --no-deps + + - name: Run Clippy on `haloumi-backend` + if: always() + run: cargo clippy -p haloumi-backend --all-targets --all-features -- -Dwarnings --no-deps + + # TODO: Fix the warnings in this crate before enabling this step. + # - name: Run Clippy on `haloumi-picus` + # if: always() + # run: cargo clippy -p haloumi-picus --all-targets --all-features -- -Dwarnings --no-deps + + - name: Run Clippy on `haloumi-llzk` + if: always() + run: cargo clippy -p haloumi-llzk --all-targets --all-features -- -Dwarnings --no-deps - - name: Run Clippy on `core` + - name: Run Clippy on `haloumi` if: always() - run: cargo clippy -p haloumi-core --all-targets --all-features -- -Dwarnings + run: cargo clippy -p haloumi --all-targets --all-features -- -Dwarnings --no-deps diff --git a/.gitignore b/.gitignore index 2f231d4..6178bd7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ debug/ target/ +build-tools/ + # These are backup files generated by rustfmt **/*.rs.bk diff --git a/.rustfmt.toml b/.rustfmt.toml index 622a219..03a0d53 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -25,7 +25,7 @@ use_try_shorthand = true use_field_init_shorthand = true force_explicit_abi = true disable_all_formatting = false -unstable_features = true -wrap_comments = true -normalize_comments = true -comment_width = 100 +# unstable_features = true +# wrap_comments = true +# normalize_comments = true +# comment_width = 100 diff --git a/Cargo.lock b/Cargo.lock index 51612b7..dd39e13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "addchain" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" +checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8" dependencies = [ "num-bigint 0.3.3", "num-integer", @@ -36,15 +36,15 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "arrayref" @@ -54,15 +54,15 @@ checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "f02882884d3e1bc524fb12c79f107f6ad0e1cfd498c536ffb494301740995dfe" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "bindgen" @@ -80,8 +80,8 @@ dependencies = [ "quote", "regex", "rustc-hash", - "shlex", - "syn 2.0.111", + "shlex 1.3.0", + "syn 2.0.118", ] [[package]] @@ -100,8 +100,8 @@ dependencies = [ "quote", "regex", "rustc-hash", - "shlex", - "syn 2.0.111", + "shlex 1.3.0", + "syn 2.0.118", ] [[package]] @@ -121,15 +121,15 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "bitvec" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" dependencies = [ "funty", "radium", @@ -180,20 +180,20 @@ dependencies = [ [[package]] name = "bstr" -version = "1.12.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79" dependencies = [ "memchr", "regex-automata", - "serde", + "serde_core", ] [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "byte-slice-cast" @@ -224,12 +224,12 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.55" +version = "1.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" +checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" dependencies = [ "find-msvc-tools", - "shlex", + "shlex 2.0.1", ] [[package]] @@ -287,18 +287,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.57" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.57" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstyle", "clap_lex", @@ -306,18 +306,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" - -[[package]] -name = "cmake" -version = "0.1.57" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" -dependencies = [ - "cc", -] +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "comrak" @@ -445,9 +436,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", ] @@ -477,9 +468,9 @@ checksum = "c37b399c91d093763e38c7a57a740e0005e30e5aff7132e791aada5eef3fed99" [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "encode_unicode" @@ -494,15 +485,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" [[package]] -name = "env_logger" -version = "0.8.4" +name = "env_filter" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217" dependencies = [ "log", "regex", ] +[[package]] +name = "env_logger" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de671bd27a75a797dc9ae289ba1e77276e75e2026408aab65185384e2d5cd3f6" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -515,22 +516,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0349da71389e03ffaf540a489eb71bc7d13492892882688f250ee48975d888ac" -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - [[package]] name = "ff" version = "0.13.1" @@ -540,7 +525,7 @@ dependencies = [ "bitvec", "byteorder", "ff_derive", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -579,44 +564,43 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.118", ] [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-timer" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +checksum = "af43fadb8a98512d547e37b4e92e0ced13e205c061b87b4623eff01d918d6968" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-core", "futures-macro", "futures-task", "pin-project-lite", - "pin-utils", "slab", ] @@ -632,9 +616,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", @@ -645,14 +629,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi", - "wasip2", + "rand_core 0.10.1", ] [[package]] @@ -668,8 +652,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand", - "rand_core", + "rand 0.8.6", + "rand_core 0.6.4", "rand_xorshift", "subtle", ] @@ -685,6 +669,22 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "halo2_proofs" +version = "0.3.2" +source = "git+https://github.com/project-llzk/halo2.git?branch=haloumi-integration#2af013987b6fa0334f4728daec9336e84ce93fbb" +dependencies = [ + "blake2b_simd", + "ff", + "group", + "haloumi", + "indexmap 1.9.3", + "maybe-rayon", + "pasta_curves", + "rand_core 0.6.4", + "tracing", +] + [[package]] name = "halo2curves" version = "0.7.0" @@ -703,8 +703,8 @@ dependencies = [ "pairing", "pasta_curves", "paste", - "rand", - "rand_core", + "rand 0.8.6", + "rand_core 0.6.4", "rayon", "sha2", "static_assertions", @@ -730,7 +730,7 @@ dependencies = [ "pairing", "paste", "plonky2_maybe_rayon", - "rand_core", + "rand_core 0.6.4", "sha2", "static_assertions", "subtle", @@ -766,20 +766,22 @@ dependencies = [ [[package]] name = "haloumi" -version = "0.5.11" +version = "0.5.15" dependencies = [ "anyhow", "ff", "group", + "halo2_proofs", "halo2curves 0.7.0", "haloumi-core", "haloumi-ir", "haloumi-ir-gen", "haloumi-llzk", + "haloumi-mdnt-test-circuits", "haloumi-midnight-integration", "haloumi-picus", "haloumi-synthesis", - "haloumi-test-circuits", + "haloumi-zcash-test-circuits", "llzk", "log", "mlir-testutils", @@ -790,11 +792,12 @@ dependencies = [ "similar-asserts", "simplelog", "thiserror", + "time", ] [[package]] name = "haloumi-backend" -version = "0.5.11" +version = "0.5.15" dependencies = [ "disjoint", "eqv", @@ -809,7 +812,7 @@ dependencies = [ [[package]] name = "haloumi-core" -version = "0.5.11" +version = "0.5.15" dependencies = [ "eqv", "ff", @@ -826,7 +829,7 @@ dependencies = [ [[package]] name = "haloumi-ir" -version = "0.5.11" +version = "0.5.15" dependencies = [ "bit-set", "eqv", @@ -846,7 +849,7 @@ dependencies = [ [[package]] name = "haloumi-ir-gen" -version = "0.5.11" +version = "0.5.15" dependencies = [ "ff", "haloumi-core", @@ -858,7 +861,7 @@ dependencies = [ [[package]] name = "haloumi-llzk" -version = "0.5.11" +version = "0.5.15" dependencies = [ "anyhow", "disjoint", @@ -890,16 +893,25 @@ dependencies = [ [[package]] name = "haloumi-lowering" -version = "0.5.11" +version = "0.5.15" dependencies = [ "ff", "haloumi-core", "thiserror", ] +[[package]] +name = "haloumi-mdnt-test-circuits" +version = "0.5.15" +dependencies = [ + "anyhow", + "ff", + "midnight-proofs", +] + [[package]] name = "haloumi-midnight-integration" -version = "0.5.11" +version = "0.5.15" dependencies = [ "ff", "haloumi-core", @@ -908,7 +920,7 @@ dependencies = [ [[package]] name = "haloumi-picus" -version = "0.5.11" +version = "0.5.15" dependencies = [ "anyhow", "criterion", @@ -930,7 +942,7 @@ dependencies = [ [[package]] name = "haloumi-synthesis" -version = "0.5.11" +version = "0.5.15" dependencies = [ "bit-set", "ff", @@ -940,14 +952,20 @@ dependencies = [ ] [[package]] -name = "haloumi-test-circuits" -version = "0.5.11" +name = "haloumi-zcash-test-circuits" +version = "0.5.15" dependencies = [ "anyhow", "ff", - "midnight-proofs", + "halo2_proofs", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.15.5" @@ -961,9 +979,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "hermit-abi" @@ -982,12 +1000,22 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.1", ] [[package]] @@ -1010,17 +1038,18 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ - "once_cell", + "cfg-if", + "futures-util", "wasm-bindgen", ] @@ -1035,9 +1064,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.178" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libloading" @@ -1051,21 +1080,15 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" - -[[package]] -name = "linux-raw-sys" -version = "0.11.0" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "llzk" -version = "0.2.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422efde88c1d445a7881c3f94c7bb8b1f6b69ac6fb44fa9307b1fbcf0e03d3ca" +checksum = "7a196255ac2d61cbfd89f8653caba09dfca95b2fc5bbcc808a627a55c771e473" dependencies = [ "llzk-macro", "llzk-sys", @@ -1079,22 +1102,22 @@ dependencies = [ [[package]] name = "llzk-macro" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e58134a3812e2e25ef0e856c0de2d4d34a8bb3fe3a3518fbba25cd111be3b569" +checksum = "380db9ed7396c5099aee48137fc036f0d622c12646ffeff958c8e0dd224bfdf7" dependencies = [ "convert_case", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.118", "thiserror", ] [[package]] name = "llzk-sys" -version = "0.2.0" +version = "30.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b6b16b5fbfbfae350c83085745c665fc9af04dea35e7bb615ff6068650575d" +checksum = "722b6d7536cd2d09e8f2af35eb6079472ba4a7eea8d524d05cfc28688ba938a8" dependencies = [ "anyhow", "llzk-sys-build-support", @@ -1103,23 +1126,29 @@ dependencies = [ [[package]] name = "llzk-sys-build-support" -version = "0.2.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673e2e1fd8cf9316a4b79e69163fd00fe57c4d0a0f4a3e93d2695687c1aeb50" +checksum = "5bf1cd6f37f319be9366795a415a7dbb02e859656ed9e867f7f6d345548a9cad" dependencies = [ "anyhow", "bindgen 0.71.1", "cc", - "cmake", - "glob", - "tempfile", ] [[package]] name = "log" -version = "0.4.29" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", +] [[package]] name = "melior" @@ -1142,16 +1171,16 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.111", + "syn 2.0.118", "tblgen", "unindent", ] [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "midnight-curves" @@ -1163,7 +1192,7 @@ dependencies = [ "byte-slice-cast", "digest", "ff", - "getrandom 0.2.16", + "getrandom 0.2.17", "group", "halo2derive 0.2.0", "hex", @@ -1171,7 +1200,7 @@ dependencies = [ "num-bigint 0.4.6", "pairing", "paste", - "rand_core", + "rand_core 0.6.4", "rayon", "serde", "serde_arrays", @@ -1186,12 +1215,12 @@ source = "git+https://github.com/Veridise/midnight-zk.git#20139c271e472fe86b9694 dependencies = [ "blake2b_simd", "ff", - "getrandom 0.2.16", + "getrandom 0.2.17", "group", "midnight-curves", "num-bigint 0.4.6", "rand_chacha", - "rand_core", + "rand_core 0.6.4", "rayon", "serde", "serde_derive", @@ -1299,9 +1328,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oorandom" @@ -1328,7 +1357,7 @@ dependencies = [ "ff", "group", "lazy_static", - "rand", + "rand 0.8.6", "static_assertions", "subtle", ] @@ -1341,15 +1370,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "plonky2_maybe_rayon" @@ -1407,63 +1430,63 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.111", + "syn 2.0.118", ] [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quickcheck" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +checksum = "95c589f335db0f6aaa168a7cd27b1fc6920f5e1470c804f814d9cd6e62a0f70b" dependencies = [ "env_logger", "log", - "rand", + "rand 0.10.1", ] [[package]] name = "quickcheck_macros" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71ee38b42f8459a88d3362be6f9b841ad2d5421844f61eb1c59c11bff3ac14a" +checksum = "a9a28b8493dd664c8b171dd944da82d933f7d456b829bfb236738e1fe06c5ba4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.118", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.3.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "radium" @@ -1473,13 +1496,23 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "getrandom 0.4.3", + "rand_core 0.10.1", ] [[package]] @@ -1489,7 +1522,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -1498,23 +1531,29 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "rand_xorshift" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -1532,9 +1571,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.2" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", @@ -1544,9 +1583,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -1555,9 +1594,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "relative-path" @@ -1590,15 +1629,15 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.111", + "syn 2.0.118", "unicode-ident", ] [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc_version" @@ -1609,19 +1648,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.61.2", -] - [[package]] name = "rustversion" version = "1.0.22" @@ -1639,9 +1665,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -1679,14 +1705,14 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.118", ] [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", @@ -1712,6 +1738,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + [[package]] name = "similar" version = "2.7.0" @@ -1745,9 +1777,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slug" @@ -1790,9 +1822,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -1817,19 +1849,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "tempfile" -version = "3.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" -dependencies = [ - "fastrand", - "getrandom 0.3.4", - "once_cell", - "rustix", - "windows-sys 0.61.2", -] - [[package]] name = "termcolor" version = "1.4.1" @@ -1841,22 +1860,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.118", ] [[package]] @@ -1870,9 +1889,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" dependencies = [ "deranged", "itoa", @@ -1880,22 +1899,22 @@ dependencies = [ "num-conv", "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" dependencies = [ "num-conv", "time-core", @@ -1913,9 +1932,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -1928,20 +1947,20 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml_datetime" -version = "0.7.3" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.23.9" +version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ - "indexmap", + "indexmap 2.14.0", "toml_datetime", "toml_parser", "winnow", @@ -1949,9 +1968,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.4" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ "winnow", ] @@ -1975,7 +1994,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.118", ] [[package]] @@ -1995,15 +2014,15 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-normalization" @@ -2016,9 +2035,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode_categories" @@ -2064,20 +2083,11 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasip2" -version = "1.0.2+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" -dependencies = [ - "wit-bindgen", -] - [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -2088,9 +2098,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2098,31 +2108,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.118", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.85" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -2227,19 +2237,13 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.14" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" - [[package]] name = "wyz" version = "0.5.1" @@ -2251,46 +2255,46 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.38" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57cf3aa6855b23711ee9852dfc97dfaa51c45feaba5b645d0c777414d494a961" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.38" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a616990af1a287837c4fe6596ad77ef57948f787e46ce28e166facc0cc1cb75" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.118", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.118", ] [[package]] name = "zmij" -version = "1.0.19" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index 0441635..d170c1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,12 +10,13 @@ members = [ "llzk", "driver", "support/midnight", - "support/test-circuits" + "support/mdnt-test-circuits", + "support/zcash-test-circuits" ] resolver = "2" [workspace.package] -version = "0.5.11" +version = "0.5.15" authors = ["Daniel Dominguez (Veridise) "] edition = "2024" rust-version = "1.85" @@ -34,9 +35,13 @@ log = "0.4" eqv = "0.1" bit-set = "0.8" disjoint = "0.8" -llzk = { version = "0.2.0", features =["bigint"] } +llzk = { version = "0.6.0", features =["bigint"] } # Testing dependencies halo2curves = "0.7.0" similar-asserts = "1.7" mlir-testutils = {version = "0.1.0", features = ["similar-asserts"]} + +# Patch haloumi dependency of ZCash's Halo2 with the local version for testing. +[patch.crates-io] +haloumi = { path = "driver/" } diff --git a/core/src/info_traits.rs b/core/src/info_traits.rs index 6d314dd..d829a93 100644 --- a/core/src/info_traits.rs +++ b/core/src/info_traits.rs @@ -21,7 +21,7 @@ pub trait ConstraintSystemInfo { fn gates(&self) -> Vec<&dyn GateInfo>; /// Returns a list with data about the lookups defined in the system. - fn lookups(&self) -> Vec>; + fn lookups(&self) -> Vec>; } /// Trait for querying information about the a gate in the constraint system. diff --git a/driver/Cargo.toml b/driver/Cargo.toml index f65eace..ff6ea4c 100644 --- a/driver/Cargo.toml +++ b/driver/Cargo.toml @@ -23,11 +23,14 @@ thiserror.workspace = true [dev-dependencies] simplelog = {version = "0.12", features = ["test"] } +# Set to 0.3.45 since that's the last version compatible with Rust 1.85 +time = "0.3.45" quickcheck = "1" quickcheck_macros = "1" rstest = "0.26" group = "0.13" -haloumi-test-circuits = { path = "../support/test-circuits" } +haloumi-mdnt-test-circuits = { path = "../support/mdnt-test-circuits" } +haloumi-zcash-test-circuits = { path = "../support/zcash-test-circuits" } haloumi-midnight-integration = { path = "../support/midnight" } paste = "1" anyhow = "1" @@ -37,6 +40,16 @@ similar-asserts.workspace = true mlir-testutils.workspace = true llzk.workspace = true +[dev-dependencies.zcash-halo2_proofs] +git = "https://github.com/project-llzk/halo2.git" +branch = "haloumi-integration" +default-features = false +features = [ + "region-groups", + "haloumi" +] +package = "halo2_proofs" + [features] default = ["llzk-backend", "picus-backend"] llzk-backend = ["dep:haloumi-llzk"] diff --git a/driver/src/lib.rs b/driver/src/lib.rs index e921af3..b76fad5 100644 --- a/driver/src/lib.rs +++ b/driver/src/lib.rs @@ -12,11 +12,12 @@ pub mod error; /// Re-export of `haloumi-ir`. pub mod ir { pub use haloumi_ir::*; + /// Re-export of `haloumi-ir-gen` + pub mod r#gen { + pub use haloumi_ir_gen::*; + } } -/// Re-export of `haloumi-ir-gen` -pub mod ir_gen { - pub use haloumi_ir_gen::*; -} + /// Re-export of `haloumi-synthesis` pub mod synthesis { pub use haloumi_synthesis::*; @@ -25,3 +26,18 @@ pub mod synthesis { pub mod core { pub use haloumi_core::*; } + +/// Haloumi backends re-exports. +pub mod backends { + /// Re-export of `haloumi-picus` + #[cfg(feature = "picus-backend")] + pub mod picus { + pub use haloumi_picus::*; + } + + /// Re-export of `haloumi-llzk` + #[cfg(feature = "llzk-backend")] + pub mod llzk { + pub use haloumi_llzk::*; + } +} diff --git a/driver/tests/expected/llzk/deep_callstack.mlir b/driver/tests/expected/llzk/deep_callstack.mlir new file mode 100644 index 0000000..3b64541 --- /dev/null +++ b/driver/tests/expected/llzk/deep_callstack.mlir @@ -0,0 +1,183 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @"test group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"test group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group"<[]>> + function.return %self : !struct.type<@"test group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %0 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %1 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %3 = felt.neg %2 : !felt.type<"bn254"> + %4 = felt.add %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = felt.mul %felt_const_1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %5, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %6 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_1_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %8 = felt.mul %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + %10 = felt.neg %9 : !felt.type<"bn254"> + %11 = felt.add %8, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = felt.mul %felt_const_1_0, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %12, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %arg1, %13 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_1 : !felt.type<"bn254"> + } + struct.def @"test group1" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"test group1"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group1"<[]>> + function.return %self : !struct.type<@"test group1"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group1"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %0 = struct.readm %arg0[@adv_0_3] : <@"test group1"<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_3] : <@"test group1"<[]>>, !felt.type<"bn254"> + %2 = felt.mul %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@out_0] : <@"test group1"<[]>>, !felt.type<"bn254"> + %4 = felt.neg %3 : !felt.type<"bn254"> + %5 = felt.add %2, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = felt.mul %felt_const_1, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %6, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_0_3] : <@"test group1"<[]>>, !felt.type<"bn254"> + constrain.eq %arg1, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_3 : !felt.type<"bn254"> + struct.member @adv_1_3 : !felt.type<"bn254"> + } + struct.def @"inner group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"inner group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"inner group"<[]>> + function.return %self : !struct.type<@"inner group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"inner group"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %0 = struct.readm %arg0[@adv_0_4] : <@"inner group"<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_4] : <@"inner group"<[]>>, !felt.type<"bn254"> + %2 = felt.mul %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@out_0] : <@"inner group"<[]>>, !felt.type<"bn254"> + %4 = felt.neg %3 : !felt.type<"bn254"> + %5 = felt.add %2, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = felt.mul %felt_const_1, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %6, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_0_4] : <@"inner group"<[]>>, !felt.type<"bn254"> + constrain.eq %arg1, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_4 : !felt.type<"bn254"> + struct.member @adv_1_4 : !felt.type<"bn254"> + } + struct.def @"outer group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"outer group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"outer group"<[]>> + function.return %self : !struct.type<@"outer group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"outer group"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@"inner group_0"] : <@"outer group"<[]>>, !struct.type<@"inner group"<[]>> + function.call @"inner group"::@constrain(%0, %arg1) : (!struct.type<@"inner group"<[]>>, !felt.type<"bn254">) -> () + %1 = struct.readm %arg0[@adv_2_4] : <@"outer group"<[]>>, !felt.type<"bn254"> + %2 = struct.readm %arg0[@"inner group_0"] : <@"outer group"<[]>>, !struct.type<@"inner group"<[]>> + %3 = struct.readm %2[@out_0] : <@"inner group"<[]>>, !felt.type<"bn254"> + constrain.eq %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %4 = struct.readm %arg0[@adv_0_5] : <@"outer group"<[]>>, !felt.type<"bn254"> + %5 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = struct.readm %arg0[@adv_1_5] : <@"outer group"<[]>>, !felt.type<"bn254"> + %7 = felt.neg %6 : !felt.type<"bn254"> + %8 = felt.add %5, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = felt.mul %felt_const_1, %8 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %9, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %10 = struct.readm %arg0[@adv_0_5] : <@"outer group"<[]>>, !felt.type<"bn254"> + %11 = struct.readm %arg0[@adv_1_5] : <@"outer group"<[]>>, !felt.type<"bn254"> + %12 = felt.mul %10, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = struct.readm %arg0[@out_0] : <@"outer group"<[]>>, !felt.type<"bn254"> + %14 = felt.neg %13 : !felt.type<"bn254"> + %15 = felt.add %12, %14 : !felt.type<"bn254">, !felt.type<"bn254"> + %16 = felt.mul %felt_const_1_0, %15 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %16, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %17 = struct.readm %arg0[@adv_2_4] : <@"outer group"<[]>>, !felt.type<"bn254"> + %18 = struct.readm %arg0[@adv_0_5] : <@"outer group"<[]>>, !felt.type<"bn254"> + constrain.eq %17, %18 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @"inner group_0" : !struct.type<@"inner group"<[]>> + struct.member @adv_2_4 : !felt.type<"bn254"> + struct.member @adv_0_5 : !felt.type<"bn254"> + struct.member @adv_1_5 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%1, %0) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %2 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %3 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + %4 = struct.readm %3[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %2, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %6 = struct.readm %arg0[@"test group_1"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%6, %5) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %7 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %8 = struct.readm %arg0[@"test group_1"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + %9 = struct.readm %8[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %7, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %11 = struct.readm %arg0[@"test group1_2"] : <@Main<[]>>, !struct.type<@"test group1"<[]>> + function.call @"test group1"::@constrain(%11, %10) : (!struct.type<@"test group1"<[]>>, !felt.type<"bn254">) -> () + %12 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %13 = struct.readm %arg0[@"test group1_2"] : <@Main<[]>>, !struct.type<@"test group1"<[]>> + %14 = struct.readm %13[@out_0] : <@"test group1"<[]>>, !felt.type<"bn254"> + constrain.eq %12, %14 : !felt.type<"bn254">, !felt.type<"bn254"> + %15 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %16 = struct.readm %arg0[@"outer group_3"] : <@Main<[]>>, !struct.type<@"outer group"<[]>> + function.call @"outer group"::@constrain(%16, %15) : (!struct.type<@"outer group"<[]>>, !felt.type<"bn254">) -> () + %17 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + %18 = struct.readm %arg0[@"outer group_3"] : <@Main<[]>>, !struct.type<@"outer group"<[]>> + %19 = struct.readm %18[@out_0] : <@"outer group"<[]>>, !felt.type<"bn254"> + constrain.eq %17, %19 : !felt.type<"bn254">, !felt.type<"bn254"> + %20 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %20, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %21 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + %22 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %21, %22 : !felt.type<"bn254">, !felt.type<"bn254"> + %23 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + %24 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %23, %24 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @"test group_0" : !struct.type<@"test group"<[]>> + struct.member @adv_2_1 : !felt.type<"bn254"> + struct.member @"test group_1" : !struct.type<@"test group"<[]>> + struct.member @adv_2_2 : !felt.type<"bn254"> + struct.member @"test group1_2" : !struct.type<@"test group1"<[]>> + struct.member @adv_2_3 : !felt.type<"bn254"> + struct.member @"outer group_3" : !struct.type<@"outer group"<[]>> + struct.member @adv_2_5 : !felt.type<"bn254"> + struct.member @adv_2_6 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/deep_callstack_opt.mlir b/driver/tests/expected/llzk/deep_callstack_opt.mlir new file mode 100644 index 0000000..98f494d --- /dev/null +++ b/driver/tests/expected/llzk/deep_callstack_opt.mlir @@ -0,0 +1,131 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @"test group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"test group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group"<[]>> + function.return %self : !struct.type<@"test group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %1 = felt.neg %0 : !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_1] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = felt.mul %0, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %3, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %arg1, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_1 : !felt.type<"bn254"> + } + struct.def @"test group1" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"test group1"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group1"<[]>> + function.return %self : !struct.type<@"test group1"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group1"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_3] : <@"test group1"<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_3] : <@"test group1"<[]>>, !felt.type<"bn254"> + %2 = felt.mul %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@out_0] : <@"test group1"<[]>>, !felt.type<"bn254"> + constrain.eq %2, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %arg1, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_3 : !felt.type<"bn254"> + struct.member @adv_1_3 : !felt.type<"bn254"> + } + struct.def @"inner group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"inner group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"inner group"<[]>> + function.return %self : !struct.type<@"inner group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"inner group"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_4] : <@"inner group"<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_4] : <@"inner group"<[]>>, !felt.type<"bn254"> + %2 = felt.mul %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@out_0] : <@"inner group"<[]>>, !felt.type<"bn254"> + constrain.eq %2, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %arg1, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_4 : !felt.type<"bn254"> + struct.member @adv_1_4 : !felt.type<"bn254"> + } + struct.def @"outer group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"outer group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"outer group"<[]>> + function.return %self : !struct.type<@"outer group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"outer group"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@"inner group_0"] : <@"outer group"<[]>>, !struct.type<@"inner group"<[]>> + function.call @"inner group"::@constrain(%0, %arg1) : (!struct.type<@"inner group"<[]>>, !felt.type<"bn254">) -> () + %1 = struct.readm %arg0[@adv_2_4] : <@"outer group"<[]>>, !felt.type<"bn254"> + %2 = struct.readm %0[@out_0] : <@"inner group"<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@adv_0_5] : <@"outer group"<[]>>, !felt.type<"bn254"> + %4 = felt.neg %3 : !felt.type<"bn254"> + %5 = struct.readm %arg0[@adv_1_5] : <@"outer group"<[]>>, !felt.type<"bn254"> + constrain.eq %4, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = felt.mul %3, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@out_0] : <@"outer group"<[]>>, !felt.type<"bn254"> + constrain.eq %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @"inner group_0" : !struct.type<@"inner group"<[]>> + struct.member @adv_2_4 : !felt.type<"bn254"> + struct.member @adv_0_5 : !felt.type<"bn254"> + struct.member @adv_1_5 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%1, %0) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %2 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %3 = struct.readm %1[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %2, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@"test group_1"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%4, %2) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %5 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %6 = struct.readm %4[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %5, %6 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@"test group1_2"] : <@Main<[]>>, !struct.type<@"test group1"<[]>> + function.call @"test group1"::@constrain(%7, %5) : (!struct.type<@"test group1"<[]>>, !felt.type<"bn254">) -> () + %8 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %9 = struct.readm %7[@out_0] : <@"test group1"<[]>>, !felt.type<"bn254"> + constrain.eq %8, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@"outer group_3"] : <@Main<[]>>, !struct.type<@"outer group"<[]>> + function.call @"outer group"::@constrain(%10, %8) : (!struct.type<@"outer group"<[]>>, !felt.type<"bn254">) -> () + %11 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + %12 = struct.readm %10[@out_0] : <@"outer group"<[]>>, !felt.type<"bn254"> + constrain.eq %11, %12 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %11, %13 : !felt.type<"bn254">, !felt.type<"bn254"> + %14 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %13, %14 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @"test group_0" : !struct.type<@"test group"<[]>> + struct.member @adv_2_1 : !felt.type<"bn254"> + struct.member @"test group_1" : !struct.type<@"test group"<[]>> + struct.member @adv_2_2 : !felt.type<"bn254"> + struct.member @"test group1_2" : !struct.type<@"test group1"<[]>> + struct.member @adv_2_3 : !felt.type<"bn254"> + struct.member @"outer group_3" : !struct.type<@"outer group"<[]>> + struct.member @adv_2_5 : !felt.type<"bn254"> + struct.member @adv_2_6 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/different_bodies.mlir b/driver/tests/expected/llzk/different_bodies.mlir new file mode 100644 index 0000000..9176484 --- /dev/null +++ b/driver/tests/expected/llzk/different_bodies.mlir @@ -0,0 +1,107 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @"test group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"test group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group"<[]>> + function.return %self : !struct.type<@"test group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %0 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %1 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %3 = felt.neg %2 : !felt.type<"bn254"> + %4 = felt.add %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = felt.mul %felt_const_1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %5, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %6 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_1_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %8 = felt.mul %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + %10 = felt.neg %9 : !felt.type<"bn254"> + %11 = felt.add %8, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = felt.mul %felt_const_1_0, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %12, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %arg1, %13 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_1 : !felt.type<"bn254"> + } + struct.def @"test group1" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"test group1"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group1"<[]>> + function.return %self : !struct.type<@"test group1"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group1"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %0 = struct.readm %arg0[@adv_0_3] : <@"test group1"<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_3] : <@"test group1"<[]>>, !felt.type<"bn254"> + %2 = felt.mul %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@out_0] : <@"test group1"<[]>>, !felt.type<"bn254"> + %4 = felt.neg %3 : !felt.type<"bn254"> + %5 = felt.add %2, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = felt.mul %felt_const_1, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %6, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_0_3] : <@"test group1"<[]>>, !felt.type<"bn254"> + constrain.eq %arg1, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_3 : !felt.type<"bn254"> + struct.member @adv_1_3 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%1, %0) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %2 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %3 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + %4 = struct.readm %3[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %2, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %6 = struct.readm %arg0[@"test group_1"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%6, %5) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %7 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %8 = struct.readm %arg0[@"test group_1"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + %9 = struct.readm %8[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %7, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %11 = struct.readm %arg0[@"test group1_2"] : <@Main<[]>>, !struct.type<@"test group1"<[]>> + function.call @"test group1"::@constrain(%11, %10) : (!struct.type<@"test group1"<[]>>, !felt.type<"bn254">) -> () + %12 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %13 = struct.readm %arg0[@"test group1_2"] : <@Main<[]>>, !struct.type<@"test group1"<[]>> + %14 = struct.readm %13[@out_0] : <@"test group1"<[]>>, !felt.type<"bn254"> + constrain.eq %12, %14 : !felt.type<"bn254">, !felt.type<"bn254"> + %15 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %15, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %16 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %17 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %16, %17 : !felt.type<"bn254">, !felt.type<"bn254"> + %18 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + %19 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %18, %19 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @"test group_0" : !struct.type<@"test group"<[]>> + struct.member @adv_2_1 : !felt.type<"bn254"> + struct.member @"test group_1" : !struct.type<@"test group"<[]>> + struct.member @adv_2_2 : !felt.type<"bn254"> + struct.member @"test group1_2" : !struct.type<@"test group1"<[]>> + struct.member @adv_2_3 : !felt.type<"bn254"> + struct.member @adv_2_4 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/different_bodies_opt.mlir b/driver/tests/expected/llzk/different_bodies_opt.mlir new file mode 100644 index 0000000..7d705f5 --- /dev/null +++ b/driver/tests/expected/llzk/different_bodies_opt.mlir @@ -0,0 +1,79 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @"test group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"test group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group"<[]>> + function.return %self : !struct.type<@"test group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %1 = felt.neg %0 : !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_1] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = felt.mul %0, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %3, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %arg1, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_1 : !felt.type<"bn254"> + } + struct.def @"test group1" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"test group1"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group1"<[]>> + function.return %self : !struct.type<@"test group1"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group1"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_3] : <@"test group1"<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_3] : <@"test group1"<[]>>, !felt.type<"bn254"> + %2 = felt.mul %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@out_0] : <@"test group1"<[]>>, !felt.type<"bn254"> + constrain.eq %2, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %arg1, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_3 : !felt.type<"bn254"> + struct.member @adv_1_3 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%1, %0) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %2 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %3 = struct.readm %1[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %2, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@"test group_1"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%4, %2) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %5 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %6 = struct.readm %4[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %5, %6 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@"test group1_2"] : <@Main<[]>>, !struct.type<@"test group1"<[]>> + function.call @"test group1"::@constrain(%7, %5) : (!struct.type<@"test group1"<[]>>, !felt.type<"bn254">) -> () + %8 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %9 = struct.readm %7[@out_0] : <@"test group1"<[]>>, !felt.type<"bn254"> + constrain.eq %8, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %8, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + %11 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %10, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @"test group_0" : !struct.type<@"test group"<[]>> + struct.member @adv_2_1 : !felt.type<"bn254"> + struct.member @"test group_1" : !struct.type<@"test group"<[]>> + struct.member @adv_2_2 : !felt.type<"bn254"> + struct.member @"test group1_2" : !struct.type<@"test group1"<[]>> + struct.member @adv_2_3 : !felt.type<"bn254"> + struct.member @adv_2_4 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/fibonacci.mlir b/driver/tests/expected/llzk/fibonacci.mlir new file mode 100644 index 0000000..2ddd2f3 --- /dev/null +++ b/driver/tests/expected/llzk/fibonacci.mlir @@ -0,0 +1,165 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %2 = felt.add %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %4 = felt.neg %3 : !felt.type<"bn254"> + %5 = felt.add %2, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = felt.mul %felt_const_1, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %6, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %7 = struct.readm %arg0[@adv_0_1] : <@Main<[]>>, !felt.type<"bn254"> + %8 = struct.readm %arg0[@adv_1_1] : <@Main<[]>>, !felt.type<"bn254"> + %9 = felt.add %7, %8 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %11 = felt.neg %10 : !felt.type<"bn254"> + %12 = felt.add %9, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = felt.mul %felt_const_1_0, %12 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %13, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_2 = felt.const 1 <"bn254"> + %14 = struct.readm %arg0[@adv_0_2] : <@Main<[]>>, !felt.type<"bn254"> + %15 = struct.readm %arg0[@adv_1_2] : <@Main<[]>>, !felt.type<"bn254"> + %16 = felt.add %14, %15 : !felt.type<"bn254">, !felt.type<"bn254"> + %17 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %18 = felt.neg %17 : !felt.type<"bn254"> + %19 = felt.add %16, %18 : !felt.type<"bn254">, !felt.type<"bn254"> + %20 = felt.mul %felt_const_1_2, %19 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_3 = felt.const 0 <"bn254"> + constrain.eq %20, %felt_const_0_3 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_4 = felt.const 1 <"bn254"> + %21 = struct.readm %arg0[@adv_0_3] : <@Main<[]>>, !felt.type<"bn254"> + %22 = struct.readm %arg0[@adv_1_3] : <@Main<[]>>, !felt.type<"bn254"> + %23 = felt.add %21, %22 : !felt.type<"bn254">, !felt.type<"bn254"> + %24 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %25 = felt.neg %24 : !felt.type<"bn254"> + %26 = felt.add %23, %25 : !felt.type<"bn254">, !felt.type<"bn254"> + %27 = felt.mul %felt_const_1_4, %26 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_5 = felt.const 0 <"bn254"> + constrain.eq %27, %felt_const_0_5 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_6 = felt.const 1 <"bn254"> + %28 = struct.readm %arg0[@adv_0_4] : <@Main<[]>>, !felt.type<"bn254"> + %29 = struct.readm %arg0[@adv_1_4] : <@Main<[]>>, !felt.type<"bn254"> + %30 = felt.add %28, %29 : !felt.type<"bn254">, !felt.type<"bn254"> + %31 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + %32 = felt.neg %31 : !felt.type<"bn254"> + %33 = felt.add %30, %32 : !felt.type<"bn254">, !felt.type<"bn254"> + %34 = felt.mul %felt_const_1_6, %33 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_7 = felt.const 0 <"bn254"> + constrain.eq %34, %felt_const_0_7 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_8 = felt.const 1 <"bn254"> + %35 = struct.readm %arg0[@adv_0_5] : <@Main<[]>>, !felt.type<"bn254"> + %36 = struct.readm %arg0[@adv_1_5] : <@Main<[]>>, !felt.type<"bn254"> + %37 = felt.add %35, %36 : !felt.type<"bn254">, !felt.type<"bn254"> + %38 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + %39 = felt.neg %38 : !felt.type<"bn254"> + %40 = felt.add %37, %39 : !felt.type<"bn254">, !felt.type<"bn254"> + %41 = felt.mul %felt_const_1_8, %40 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_9 = felt.const 0 <"bn254"> + constrain.eq %41, %felt_const_0_9 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_10 = felt.const 1 <"bn254"> + %42 = struct.readm %arg0[@adv_0_6] : <@Main<[]>>, !felt.type<"bn254"> + %43 = struct.readm %arg0[@adv_1_6] : <@Main<[]>>, !felt.type<"bn254"> + %44 = felt.add %42, %43 : !felt.type<"bn254">, !felt.type<"bn254"> + %45 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + %46 = felt.neg %45 : !felt.type<"bn254"> + %47 = felt.add %44, %46 : !felt.type<"bn254">, !felt.type<"bn254"> + %48 = felt.mul %felt_const_1_10, %47 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_11 = felt.const 0 <"bn254"> + constrain.eq %48, %felt_const_0_11 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_12 = felt.const 1 <"bn254"> + %49 = struct.readm %arg0[@adv_0_7] : <@Main<[]>>, !felt.type<"bn254"> + %50 = struct.readm %arg0[@adv_1_7] : <@Main<[]>>, !felt.type<"bn254"> + %51 = felt.add %49, %50 : !felt.type<"bn254">, !felt.type<"bn254"> + %52 = struct.readm %arg0[@adv_2_7] : <@Main<[]>>, !felt.type<"bn254"> + %53 = felt.neg %52 : !felt.type<"bn254"> + %54 = felt.add %51, %53 : !felt.type<"bn254">, !felt.type<"bn254"> + %55 = felt.mul %felt_const_1_12, %54 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_13 = felt.const 0 <"bn254"> + constrain.eq %55, %felt_const_0_13 : !felt.type<"bn254">, !felt.type<"bn254"> + %56 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %56, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %57 = struct.readm %arg0[@adv_0_1] : <@Main<[]>>, !felt.type<"bn254"> + %58 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %57, %58 : !felt.type<"bn254">, !felt.type<"bn254"> + %59 = struct.readm %arg0[@adv_0_2] : <@Main<[]>>, !felt.type<"bn254"> + %60 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %59, %60 : !felt.type<"bn254">, !felt.type<"bn254"> + %61 = struct.readm %arg0[@adv_0_3] : <@Main<[]>>, !felt.type<"bn254"> + %62 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %61, %62 : !felt.type<"bn254">, !felt.type<"bn254"> + %63 = struct.readm %arg0[@adv_0_4] : <@Main<[]>>, !felt.type<"bn254"> + %64 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %63, %64 : !felt.type<"bn254">, !felt.type<"bn254"> + %65 = struct.readm %arg0[@adv_0_5] : <@Main<[]>>, !felt.type<"bn254"> + %66 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %65, %66 : !felt.type<"bn254">, !felt.type<"bn254"> + %67 = struct.readm %arg0[@adv_0_6] : <@Main<[]>>, !felt.type<"bn254"> + %68 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %67, %68 : !felt.type<"bn254">, !felt.type<"bn254"> + %69 = struct.readm %arg0[@adv_0_7] : <@Main<[]>>, !felt.type<"bn254"> + %70 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %69, %70 : !felt.type<"bn254">, !felt.type<"bn254"> + %71 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %71, %arg2 : !felt.type<"bn254">, !felt.type<"bn254"> + %72 = struct.readm %arg0[@adv_1_1] : <@Main<[]>>, !felt.type<"bn254"> + %73 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %72, %73 : !felt.type<"bn254">, !felt.type<"bn254"> + %74 = struct.readm %arg0[@adv_1_2] : <@Main<[]>>, !felt.type<"bn254"> + %75 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %74, %75 : !felt.type<"bn254">, !felt.type<"bn254"> + %76 = struct.readm %arg0[@adv_1_3] : <@Main<[]>>, !felt.type<"bn254"> + %77 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %76, %77 : !felt.type<"bn254">, !felt.type<"bn254"> + %78 = struct.readm %arg0[@adv_1_4] : <@Main<[]>>, !felt.type<"bn254"> + %79 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %78, %79 : !felt.type<"bn254">, !felt.type<"bn254"> + %80 = struct.readm %arg0[@adv_1_5] : <@Main<[]>>, !felt.type<"bn254"> + %81 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %80, %81 : !felt.type<"bn254">, !felt.type<"bn254"> + %82 = struct.readm %arg0[@adv_1_6] : <@Main<[]>>, !felt.type<"bn254"> + %83 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %82, %83 : !felt.type<"bn254">, !felt.type<"bn254"> + %84 = struct.readm %arg0[@adv_1_7] : <@Main<[]>>, !felt.type<"bn254"> + %85 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %84, %85 : !felt.type<"bn254">, !felt.type<"bn254"> + %86 = struct.readm %arg0[@adv_2_7] : <@Main<[]>>, !felt.type<"bn254"> + %87 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %86, %87 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_1 : !felt.type<"bn254"> + struct.member @adv_2_1 : !felt.type<"bn254"> + struct.member @adv_0_2 : !felt.type<"bn254"> + struct.member @adv_1_2 : !felt.type<"bn254"> + struct.member @adv_2_2 : !felt.type<"bn254"> + struct.member @adv_0_3 : !felt.type<"bn254"> + struct.member @adv_1_3 : !felt.type<"bn254"> + struct.member @adv_2_3 : !felt.type<"bn254"> + struct.member @adv_0_4 : !felt.type<"bn254"> + struct.member @adv_1_4 : !felt.type<"bn254"> + struct.member @adv_2_4 : !felt.type<"bn254"> + struct.member @adv_0_5 : !felt.type<"bn254"> + struct.member @adv_1_5 : !felt.type<"bn254"> + struct.member @adv_2_5 : !felt.type<"bn254"> + struct.member @adv_0_6 : !felt.type<"bn254"> + struct.member @adv_1_6 : !felt.type<"bn254"> + struct.member @adv_2_6 : !felt.type<"bn254"> + struct.member @adv_0_7 : !felt.type<"bn254"> + struct.member @adv_1_7 : !felt.type<"bn254"> + struct.member @adv_2_7 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/fibonacci_grouped.mlir b/driver/tests/expected/llzk/fibonacci_grouped.mlir new file mode 100644 index 0000000..b954f04 --- /dev/null +++ b/driver/tests/expected/llzk/fibonacci_grouped.mlir @@ -0,0 +1,164 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @fib { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_1 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">, %arg1: !felt.type<"bn254">) -> !struct.type<@fib<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@fib<[]>> + function.return %self : !struct.type<@fib<[]>> + } + function.def @constrain(%arg0: !struct.type<@fib<[]>>, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %0 = struct.readm %arg0[@adv_0_1] : <@fib<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_1] : <@fib<[]>>, !felt.type<"bn254"> + %2 = felt.add %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + %4 = felt.neg %3 : !felt.type<"bn254"> + %5 = felt.add %2, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = felt.mul %felt_const_1, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %6, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_0_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %7, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %8 = struct.readm %arg0[@adv_1_1] : <@fib<[]>>, !felt.type<"bn254"> + %9 = struct.readm %arg0[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %8, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %arg2, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_1 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_1 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %2 = struct.readm %arg0[@fib_0] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%2, %0, %1) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %3 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %4 = struct.readm %arg0[@fib_0] : <@Main<[]>>, !struct.type<@fib<[]>> + %5 = struct.readm %4[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %3, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %7 = struct.readm %arg0[@fib_0] : <@Main<[]>>, !struct.type<@fib<[]>> + %8 = struct.readm %7[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %6, %8 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %10 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %11 = struct.readm %arg0[@fib_1] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%11, %9, %10) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %12 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %13 = struct.readm %arg0[@fib_1] : <@Main<[]>>, !struct.type<@fib<[]>> + %14 = struct.readm %13[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %12, %14 : !felt.type<"bn254">, !felt.type<"bn254"> + %15 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %16 = struct.readm %arg0[@fib_1] : <@Main<[]>>, !struct.type<@fib<[]>> + %17 = struct.readm %16[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %15, %17 : !felt.type<"bn254">, !felt.type<"bn254"> + %18 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %19 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %20 = struct.readm %arg0[@fib_2] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%20, %18, %19) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %21 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %22 = struct.readm %arg0[@fib_2] : <@Main<[]>>, !struct.type<@fib<[]>> + %23 = struct.readm %22[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %21, %23 : !felt.type<"bn254">, !felt.type<"bn254"> + %24 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %25 = struct.readm %arg0[@fib_2] : <@Main<[]>>, !struct.type<@fib<[]>> + %26 = struct.readm %25[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %24, %26 : !felt.type<"bn254">, !felt.type<"bn254"> + %27 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %28 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %29 = struct.readm %arg0[@fib_3] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%29, %27, %28) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %30 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %31 = struct.readm %arg0[@fib_3] : <@Main<[]>>, !struct.type<@fib<[]>> + %32 = struct.readm %31[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %30, %32 : !felt.type<"bn254">, !felt.type<"bn254"> + %33 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + %34 = struct.readm %arg0[@fib_3] : <@Main<[]>>, !struct.type<@fib<[]>> + %35 = struct.readm %34[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %33, %35 : !felt.type<"bn254">, !felt.type<"bn254"> + %36 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %37 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + %38 = struct.readm %arg0[@fib_4] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%38, %36, %37) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %39 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + %40 = struct.readm %arg0[@fib_4] : <@Main<[]>>, !struct.type<@fib<[]>> + %41 = struct.readm %40[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %39, %41 : !felt.type<"bn254">, !felt.type<"bn254"> + %42 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + %43 = struct.readm %arg0[@fib_4] : <@Main<[]>>, !struct.type<@fib<[]>> + %44 = struct.readm %43[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %42, %44 : !felt.type<"bn254">, !felt.type<"bn254"> + %45 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + %46 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + %47 = struct.readm %arg0[@fib_5] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%47, %45, %46) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %48 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + %49 = struct.readm %arg0[@fib_5] : <@Main<[]>>, !struct.type<@fib<[]>> + %50 = struct.readm %49[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %48, %50 : !felt.type<"bn254">, !felt.type<"bn254"> + %51 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + %52 = struct.readm %arg0[@fib_5] : <@Main<[]>>, !struct.type<@fib<[]>> + %53 = struct.readm %52[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %51, %53 : !felt.type<"bn254">, !felt.type<"bn254"> + %54 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + %55 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + %56 = struct.readm %arg0[@fib_6] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%56, %54, %55) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %57 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + %58 = struct.readm %arg0[@fib_6] : <@Main<[]>>, !struct.type<@fib<[]>> + %59 = struct.readm %58[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %57, %59 : !felt.type<"bn254">, !felt.type<"bn254"> + %60 = struct.readm %arg0[@adv_2_7] : <@Main<[]>>, !felt.type<"bn254"> + %61 = struct.readm %arg0[@fib_6] : <@Main<[]>>, !struct.type<@fib<[]>> + %62 = struct.readm %61[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %60, %62 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1 = felt.const 1 <"bn254"> + %63 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %64 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %65 = felt.add %63, %64 : !felt.type<"bn254">, !felt.type<"bn254"> + %66 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %67 = felt.neg %66 : !felt.type<"bn254"> + %68 = felt.add %65, %67 : !felt.type<"bn254">, !felt.type<"bn254"> + %69 = felt.mul %felt_const_1, %68 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %69, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %70 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %70, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %71 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %71, %arg2 : !felt.type<"bn254">, !felt.type<"bn254"> + %72 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + %73 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %72, %73 : !felt.type<"bn254">, !felt.type<"bn254"> + %74 = struct.readm %arg0[@adv_2_7] : <@Main<[]>>, !felt.type<"bn254"> + %75 = struct.readm %arg0[@out_1] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %74, %75 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @fib_0 : !struct.type<@fib<[]>> + struct.member @adv_2_1 : !felt.type<"bn254"> + struct.member @fib_1 : !struct.type<@fib<[]>> + struct.member @adv_2_2 : !felt.type<"bn254"> + struct.member @fib_2 : !struct.type<@fib<[]>> + struct.member @adv_2_3 : !felt.type<"bn254"> + struct.member @fib_3 : !struct.type<@fib<[]>> + struct.member @adv_2_4 : !felt.type<"bn254"> + struct.member @fib_4 : !struct.type<@fib<[]>> + struct.member @adv_2_5 : !felt.type<"bn254"> + struct.member @fib_5 : !struct.type<@fib<[]>> + struct.member @adv_2_6 : !felt.type<"bn254"> + struct.member @fib_6 : !struct.type<@fib<[]>> + struct.member @adv_2_7 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/fibonacci_grouped_opt.mlir b/driver/tests/expected/llzk/fibonacci_grouped_opt.mlir new file mode 100644 index 0000000..ea11d92 --- /dev/null +++ b/driver/tests/expected/llzk/fibonacci_grouped_opt.mlir @@ -0,0 +1,112 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @fib { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_1 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">, %arg1: !felt.type<"bn254">) -> !struct.type<@fib<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@fib<[]>> + function.return %self : !struct.type<@fib<[]>> + } + function.def @constrain(%arg0: !struct.type<@fib<[]>>, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_1] : <@fib<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_1] : <@fib<[]>>, !felt.type<"bn254"> + %2 = felt.add %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %2, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %arg2, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_1 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_1 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %2 = struct.readm %arg0[@fib_0] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%2, %0, %1) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %3 = struct.readm %2[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %5 = struct.readm %2[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %4, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = struct.readm %arg0[@fib_1] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%6, %1, %4) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %7 = struct.readm %6[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %4, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %8 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %9 = struct.readm %6[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %8, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@fib_2] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%10, %4, %8) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %11 = struct.readm %10[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %8, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %13 = struct.readm %10[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %12, %13 : !felt.type<"bn254">, !felt.type<"bn254"> + %14 = struct.readm %arg0[@fib_3] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%14, %8, %12) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %15 = struct.readm %14[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %12, %15 : !felt.type<"bn254">, !felt.type<"bn254"> + %16 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + %17 = struct.readm %14[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %16, %17 : !felt.type<"bn254">, !felt.type<"bn254"> + %18 = struct.readm %arg0[@fib_4] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%18, %12, %16) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %19 = struct.readm %18[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %16, %19 : !felt.type<"bn254">, !felt.type<"bn254"> + %20 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + %21 = struct.readm %18[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %20, %21 : !felt.type<"bn254">, !felt.type<"bn254"> + %22 = struct.readm %arg0[@fib_5] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%22, %16, %20) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %23 = struct.readm %22[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %20, %23 : !felt.type<"bn254">, !felt.type<"bn254"> + %24 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + %25 = struct.readm %22[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %24, %25 : !felt.type<"bn254">, !felt.type<"bn254"> + %26 = struct.readm %arg0[@fib_6] : <@Main<[]>>, !struct.type<@fib<[]>> + function.call @fib::@constrain(%26, %20, %24) : (!struct.type<@fib<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %27 = struct.readm %26[@out_0] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %24, %27 : !felt.type<"bn254">, !felt.type<"bn254"> + %28 = struct.readm %arg0[@adv_2_7] : <@Main<[]>>, !felt.type<"bn254"> + %29 = struct.readm %26[@out_1] : <@fib<[]>>, !felt.type<"bn254"> + constrain.eq %28, %29 : !felt.type<"bn254">, !felt.type<"bn254"> + %30 = felt.add %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %31 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %30, %31 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %1, %arg2 : !felt.type<"bn254">, !felt.type<"bn254"> + %32 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %24, %32 : !felt.type<"bn254">, !felt.type<"bn254"> + %33 = struct.readm %arg0[@out_1] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %28, %33 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @fib_0 : !struct.type<@fib<[]>> + struct.member @adv_2_1 : !felt.type<"bn254"> + struct.member @fib_1 : !struct.type<@fib<[]>> + struct.member @adv_2_2 : !felt.type<"bn254"> + struct.member @fib_2 : !struct.type<@fib<[]>> + struct.member @adv_2_3 : !felt.type<"bn254"> + struct.member @fib_3 : !struct.type<@fib<[]>> + struct.member @adv_2_4 : !felt.type<"bn254"> + struct.member @fib_4 : !struct.type<@fib<[]>> + struct.member @adv_2_5 : !felt.type<"bn254"> + struct.member @fib_5 : !struct.type<@fib<[]>> + struct.member @adv_2_6 : !felt.type<"bn254"> + struct.member @fib_6 : !struct.type<@fib<[]>> + struct.member @adv_2_7 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/fibonacci_opt.mlir b/driver/tests/expected/llzk/fibonacci_opt.mlir new file mode 100644 index 0000000..15be06c --- /dev/null +++ b/driver/tests/expected/llzk/fibonacci_opt.mlir @@ -0,0 +1,94 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %2 = felt.add %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %2, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@adv_0_1] : <@Main<[]>>, !felt.type<"bn254"> + %5 = struct.readm %arg0[@adv_1_1] : <@Main<[]>>, !felt.type<"bn254"> + %6 = felt.add %4, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %8 = struct.readm %arg0[@adv_0_2] : <@Main<[]>>, !felt.type<"bn254"> + %9 = struct.readm %arg0[@adv_1_2] : <@Main<[]>>, !felt.type<"bn254"> + %10 = felt.add %8, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + %11 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %10, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = struct.readm %arg0[@adv_0_3] : <@Main<[]>>, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_1_3] : <@Main<[]>>, !felt.type<"bn254"> + %14 = felt.add %12, %13 : !felt.type<"bn254">, !felt.type<"bn254"> + %15 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %14, %15 : !felt.type<"bn254">, !felt.type<"bn254"> + %16 = struct.readm %arg0[@adv_0_4] : <@Main<[]>>, !felt.type<"bn254"> + %17 = struct.readm %arg0[@adv_1_4] : <@Main<[]>>, !felt.type<"bn254"> + %18 = felt.add %16, %17 : !felt.type<"bn254">, !felt.type<"bn254"> + %19 = struct.readm %arg0[@adv_2_4] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %18, %19 : !felt.type<"bn254">, !felt.type<"bn254"> + %20 = struct.readm %arg0[@adv_0_5] : <@Main<[]>>, !felt.type<"bn254"> + %21 = struct.readm %arg0[@adv_1_5] : <@Main<[]>>, !felt.type<"bn254"> + %22 = felt.add %20, %21 : !felt.type<"bn254">, !felt.type<"bn254"> + %23 = struct.readm %arg0[@adv_2_5] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %22, %23 : !felt.type<"bn254">, !felt.type<"bn254"> + %24 = struct.readm %arg0[@adv_0_6] : <@Main<[]>>, !felt.type<"bn254"> + %25 = struct.readm %arg0[@adv_1_6] : <@Main<[]>>, !felt.type<"bn254"> + %26 = felt.add %24, %25 : !felt.type<"bn254">, !felt.type<"bn254"> + %27 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %26, %27 : !felt.type<"bn254">, !felt.type<"bn254"> + %28 = struct.readm %arg0[@adv_0_7] : <@Main<[]>>, !felt.type<"bn254"> + %29 = struct.readm %arg0[@adv_1_7] : <@Main<[]>>, !felt.type<"bn254"> + %30 = felt.add %28, %29 : !felt.type<"bn254">, !felt.type<"bn254"> + %31 = struct.readm %arg0[@adv_2_7] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %30, %31 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %4, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %8, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %12, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %16, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %20, %15 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %24, %19 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %28, %23 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %1, %arg2 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %5, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %9, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %13, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %17, %15 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %21, %19 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %25, %23 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %29, %27 : !felt.type<"bn254">, !felt.type<"bn254"> + %32 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %31, %32 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_1 : !felt.type<"bn254"> + struct.member @adv_2_1 : !felt.type<"bn254"> + struct.member @adv_0_2 : !felt.type<"bn254"> + struct.member @adv_1_2 : !felt.type<"bn254"> + struct.member @adv_2_2 : !felt.type<"bn254"> + struct.member @adv_0_3 : !felt.type<"bn254"> + struct.member @adv_1_3 : !felt.type<"bn254"> + struct.member @adv_2_3 : !felt.type<"bn254"> + struct.member @adv_0_4 : !felt.type<"bn254"> + struct.member @adv_1_4 : !felt.type<"bn254"> + struct.member @adv_2_4 : !felt.type<"bn254"> + struct.member @adv_0_5 : !felt.type<"bn254"> + struct.member @adv_1_5 : !felt.type<"bn254"> + struct.member @adv_2_5 : !felt.type<"bn254"> + struct.member @adv_0_6 : !felt.type<"bn254"> + struct.member @adv_1_6 : !felt.type<"bn254"> + struct.member @adv_2_6 : !felt.type<"bn254"> + struct.member @adv_0_7 : !felt.type<"bn254"> + struct.member @adv_1_7 : !felt.type<"bn254"> + struct.member @adv_2_7 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/grouped_muls.mlir b/driver/tests/expected/llzk/grouped_muls.mlir new file mode 100644 index 0000000..e52e392 --- /dev/null +++ b/driver/tests/expected/llzk/grouped_muls.mlir @@ -0,0 +1,55 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @"test group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute() -> !struct.type<@"test group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group"<[]>> + function.return %self : !struct.type<@"test group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group"<[]>>) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %0 = struct.readm %arg0[@adv_0_0] : <@"test group"<[]>>, !felt.type<"bn254"> + %1 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@"test group"<[]>>, !felt.type<"bn254"> + %3 = felt.neg %2 : !felt.type<"bn254"> + %4 = felt.add %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = felt.mul %felt_const_1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %5, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %6 = struct.readm %arg0[@adv_0_0] : <@"test group"<[]>>, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_1_0] : <@"test group"<[]>>, !felt.type<"bn254"> + %8 = felt.mul %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + %10 = felt.neg %9 : !felt.type<"bn254"> + %11 = felt.add %8, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = felt.mul %felt_const_1_0, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %12, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%0) : (!struct.type<@"test group"<[]>>) -> () + %1 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %2 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + %3 = struct.readm %2[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %5 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %4, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @"test group_0" : !struct.type<@"test group"<[]>> + struct.member @adv_2_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/grouped_muls_opt.mlir b/driver/tests/expected/llzk/grouped_muls_opt.mlir new file mode 100644 index 0000000..b8476cd --- /dev/null +++ b/driver/tests/expected/llzk/grouped_muls_opt.mlir @@ -0,0 +1,40 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @"test group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute() -> !struct.type<@"test group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group"<[]>> + function.return %self : !struct.type<@"test group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group"<[]>>) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@"test group"<[]>>, !felt.type<"bn254"> + %1 = felt.neg %0 : !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = felt.mul %0, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %3, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%0) : (!struct.type<@"test group"<[]>>) -> () + %1 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %2 = struct.readm %0[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @"test group_0" : !struct.type<@"test group"<[]>> + struct.member @adv_2_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/lookup.mlir b/driver/tests/expected/llzk/lookup.mlir new file mode 100644 index 0000000..1876661 --- /dev/null +++ b/driver/tests/expected/llzk/lookup.mlir @@ -0,0 +1,41 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %0 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %2 = felt.mul %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %4 = felt.neg %3 : !felt.type<"bn254"> + %5 = felt.add %2, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = felt.mul %felt_const_1, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %6, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %7 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %8 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %9 = felt.mul %7, %8 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@adv_3_0] : <@Main<[]>>, !felt.type<"bn254"> + %11 = felt.neg %10 : !felt.type<"bn254"> + %12 = felt.add %9, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = felt.mul %felt_const_1_0, %12 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %13, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %14 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %14, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %15 = struct.readm %arg0[@adv_3_0] : <@Main<[]>>, !felt.type<"bn254"> + %16 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %15, %16 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + struct.member @adv_3_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/lookup_2x3.mlir b/driver/tests/expected/llzk/lookup_2x3.mlir new file mode 100644 index 0000000..9ac824f --- /dev/null +++ b/driver/tests/expected/llzk/lookup_2x3.mlir @@ -0,0 +1,19 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_3_0] : <@Main<[]>>, !felt.type<"bn254"> + %2 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_3_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/lookup_2x3_opt.mlir b/driver/tests/expected/llzk/lookup_2x3_opt.mlir new file mode 100644 index 0000000..9ac824f --- /dev/null +++ b/driver/tests/expected/llzk/lookup_2x3_opt.mlir @@ -0,0 +1,19 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_3_0] : <@Main<[]>>, !felt.type<"bn254"> + %2 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_3_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/lookup_opt.mlir b/driver/tests/expected/llzk/lookup_opt.mlir new file mode 100644 index 0000000..9469661 --- /dev/null +++ b/driver/tests/expected/llzk/lookup_opt.mlir @@ -0,0 +1,27 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %2 = felt.mul %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %2, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = felt.mul %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = struct.readm %arg0[@adv_3_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %4, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %1, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %5, %6 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + struct.member @adv_3_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/mul_circuit.mlir b/driver/tests/expected/llzk/mul_circuit.mlir index 067c6c6..05b5dc7 100644 --- a/driver/tests/expected/llzk/mul_circuit.mlir +++ b/driver/tests/expected/llzk/mul_circuit.mlir @@ -1,55 +1,41 @@ -module attributes {veridise.lang = "llzk"} { - struct.def @Signal<[]> { - struct.field @reg : !felt.type {llzk.pub} - function.def @compute(%arg0: !felt.type) -> !struct.type<@Signal<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Signal<[]>> - struct.writef %self[@reg] = %arg0 : <@Signal<[]>>, !felt.type - function.return %self : !struct.type<@Signal<[]>> - } - function.def @constrain(%arg0: !struct.type<@Signal<[]>>, %arg1: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %arg1 : !felt.type, !felt.type - function.return - } - } - struct.def @Main<[]> { - struct.field @out_0 : !felt.type {llzk.pub} - function.def @compute(%arg0: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { %self = struct.new : <@Main<[]>> function.return %self : !struct.type<@Main<[]>> } - function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %felt_1 = felt.const 1 - %felt_minus_1 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 - %0 = struct.readf %arg0[@adv_0_0] : <@Main<[]>>, !felt.type - %1 = felt.mul %felt_minus_1, %0 : !felt.type, !felt.type - %2 = struct.readf %arg0[@adv_1_0] : <@Main<[]>>, !felt.type - %3 = felt.neg %2 : !felt.type - %4 = felt.add %1, %3 : !felt.type, !felt.type - %5 = felt.mul %felt_1, %4 : !felt.type, !felt.type - %felt_0 = felt.const 0 - constrain.eq %5, %felt_0 : !felt.type, !felt.type - %felt_1_0 = felt.const 1 - %6 = struct.readf %arg0[@adv_0_0] : <@Main<[]>>, !felt.type - %7 = struct.readf %arg0[@adv_1_0] : <@Main<[]>>, !felt.type - %8 = felt.mul %6, %7 : !felt.type, !felt.type - %9 = struct.readf %arg0[@adv_2_0] : <@Main<[]>>, !felt.type - %10 = felt.neg %9 : !felt.type - %11 = felt.add %8, %10 : !felt.type, !felt.type - %12 = felt.mul %felt_1_0, %11 : !felt.type, !felt.type - %felt_0_1 = felt.const 0 - constrain.eq %12, %felt_0_1 : !felt.type, !felt.type - %13 = struct.readf %arg0[@adv_0_0] : <@Main<[]>>, !felt.type - %14 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %13, %14 : !felt.type, !felt.type - %15 = struct.readf %arg0[@adv_2_0] : <@Main<[]>>, !felt.type - %16 = struct.readf %arg0[@out_0] : <@Main<[]>>, !felt.type - constrain.eq %15, %16 : !felt.type, !felt.type + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_1 = felt.const 1 <"bn254"> + %felt_minus_1 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.mul %felt_minus_1, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %3 = felt.neg %2 : !felt.type<"bn254"> + %4 = felt.add %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = felt.mul %felt_1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_0 = felt.const 0 <"bn254"> + constrain.eq %5, %felt_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_1_0 = felt.const 1 <"bn254"> + %6 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %8 = felt.mul %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %10 = felt.neg %9 : !felt.type<"bn254"> + %11 = felt.add %8, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = felt.mul %felt_1_0, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_0_1 = felt.const 0 <"bn254"> + constrain.eq %12, %felt_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %13, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %15 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %16 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %15, %16 : !felt.type<"bn254">, !felt.type<"bn254"> function.return } - struct.field @adv_0_0 : !felt.type - struct.field @adv_1_0 : !felt.type - struct.field @adv_2_0 : !felt.type + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> } } diff --git a/driver/tests/expected/llzk/mul_circuit_opt.mlir b/driver/tests/expected/llzk/mul_circuit_opt.mlir index ea08483..01a921d 100644 --- a/driver/tests/expected/llzk/mul_circuit_opt.mlir +++ b/driver/tests/expected/llzk/mul_circuit_opt.mlir @@ -1,40 +1,26 @@ -module attributes {veridise.lang = "llzk"} { - struct.def @Signal<[]> { - struct.field @reg : !felt.type {llzk.pub} - function.def @compute(%arg0: !felt.type) -> !struct.type<@Signal<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Signal<[]>> - struct.writef %self[@reg] = %arg0 : <@Signal<[]>>, !felt.type - function.return %self : !struct.type<@Signal<[]>> - } - function.def @constrain(%arg0: !struct.type<@Signal<[]>>, %arg1: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %arg1 : !felt.type, !felt.type - function.return - } - } - struct.def @Main<[]> { - struct.field @out_0 : !felt.type {llzk.pub} - function.def @compute(%arg0: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { %self = struct.new : <@Main<[]>> function.return %self : !struct.type<@Main<[]>> } - function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@adv_0_0] : <@Main<[]>>, !felt.type - %1 = felt.neg %0 : !felt.type - %2 = struct.readf %arg0[@adv_1_0] : <@Main<[]>>, !felt.type - constrain.eq %1, %2 : !felt.type, !felt.type - %5 = felt.mul %0, %2 : !felt.type, !felt.type - %6 = struct.readf %arg0[@adv_2_0] : <@Main<[]>>, !felt.type - constrain.eq %5, %6 : !felt.type, !felt.type - %8 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %8 : !felt.type, !felt.type - %10 = struct.readf %arg0[@out_0] : <@Main<[]>>, !felt.type - constrain.eq %6, %10 : !felt.type, !felt.type + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.neg %0 : !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = felt.mul %0, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %5, %6 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %6, %10 : !felt.type<"bn254">, !felt.type<"bn254"> function.return } - struct.field @adv_0_0 : !felt.type - struct.field @adv_1_0 : !felt.type - struct.field @adv_2_0 : !felt.type + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> } } diff --git a/driver/tests/expected/llzk/mul_flipped_constraint.mlir b/driver/tests/expected/llzk/mul_flipped_constraint.mlir new file mode 100644 index 0000000..c9ef610 --- /dev/null +++ b/driver/tests/expected/llzk/mul_flipped_constraint.mlir @@ -0,0 +1,40 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %3 = felt.neg %2 : !felt.type<"bn254"> + %4 = felt.add %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = felt.mul %felt_const_1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %5, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %6 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %7 = felt.neg %6 : !felt.type<"bn254"> + %8 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %9 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %10 = felt.mul %8, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + %11 = felt.add %7, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = felt.mul %felt_const_1_0, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %12, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %13, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %14 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %15 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %14, %15 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/mul_flipped_constraint_opt.mlir b/driver/tests/expected/llzk/mul_flipped_constraint_opt.mlir new file mode 100644 index 0000000..b942ce7 --- /dev/null +++ b/driver/tests/expected/llzk/mul_flipped_constraint_opt.mlir @@ -0,0 +1,25 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.neg %0 : !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %4 = felt.mul %0, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %3, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %3, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/mul_inject.mlir b/driver/tests/expected/llzk/mul_inject.mlir new file mode 100644 index 0000000..bda6b35 --- /dev/null +++ b/driver/tests/expected/llzk/mul_inject.mlir @@ -0,0 +1,122 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_1 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_2 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_0_1] : <@Main<[]>>, !felt.type<"bn254"> + %3 = felt.neg %2 : !felt.type<"bn254"> + %4 = felt.add %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = felt.mul %felt_const_1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %5, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %6 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_0_1] : <@Main<[]>>, !felt.type<"bn254"> + %8 = felt.mul %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %10 = felt.neg %9 : !felt.type<"bn254"> + %11 = felt.add %8, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = felt.mul %felt_const_1_0, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %12, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_2 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616_3 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %13 = struct.readm %arg0[@adv_0_2] : <@Main<[]>>, !felt.type<"bn254"> + %14 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616_3, %13 : !felt.type<"bn254">, !felt.type<"bn254"> + %15 = struct.readm %arg0[@adv_0_3] : <@Main<[]>>, !felt.type<"bn254"> + %16 = felt.neg %15 : !felt.type<"bn254"> + %17 = felt.add %14, %16 : !felt.type<"bn254">, !felt.type<"bn254"> + %18 = felt.mul %felt_const_1_2, %17 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_4 = felt.const 0 <"bn254"> + constrain.eq %18, %felt_const_0_4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_5 = felt.const 1 <"bn254"> + %19 = struct.readm %arg0[@adv_0_2] : <@Main<[]>>, !felt.type<"bn254"> + %20 = struct.readm %arg0[@adv_0_3] : <@Main<[]>>, !felt.type<"bn254"> + %21 = felt.mul %19, %20 : !felt.type<"bn254">, !felt.type<"bn254"> + %22 = struct.readm %arg0[@adv_1_2] : <@Main<[]>>, !felt.type<"bn254"> + %23 = felt.neg %22 : !felt.type<"bn254"> + %24 = felt.add %21, %23 : !felt.type<"bn254">, !felt.type<"bn254"> + %25 = felt.mul %felt_const_1_5, %24 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_6 = felt.const 0 <"bn254"> + constrain.eq %25, %felt_const_0_6 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_7 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616_8 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %26 = struct.readm %arg0[@adv_0_4] : <@Main<[]>>, !felt.type<"bn254"> + %27 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616_8, %26 : !felt.type<"bn254">, !felt.type<"bn254"> + %28 = struct.readm %arg0[@adv_0_5] : <@Main<[]>>, !felt.type<"bn254"> + %29 = felt.neg %28 : !felt.type<"bn254"> + %30 = felt.add %27, %29 : !felt.type<"bn254">, !felt.type<"bn254"> + %31 = felt.mul %felt_const_1_7, %30 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_9 = felt.const 0 <"bn254"> + constrain.eq %31, %felt_const_0_9 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_10 = felt.const 1 <"bn254"> + %32 = struct.readm %arg0[@adv_0_4] : <@Main<[]>>, !felt.type<"bn254"> + %33 = struct.readm %arg0[@adv_0_5] : <@Main<[]>>, !felt.type<"bn254"> + %34 = felt.mul %32, %33 : !felt.type<"bn254">, !felt.type<"bn254"> + %35 = struct.readm %arg0[@adv_1_4] : <@Main<[]>>, !felt.type<"bn254"> + %36 = felt.neg %35 : !felt.type<"bn254"> + %37 = felt.add %34, %36 : !felt.type<"bn254">, !felt.type<"bn254"> + %38 = felt.mul %felt_const_1_10, %37 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_11 = felt.const 0 <"bn254"> + constrain.eq %38, %felt_const_0_11 : !felt.type<"bn254">, !felt.type<"bn254"> + %39 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %39, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %40 = struct.readm %arg0[@adv_0_2] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %40, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %41 = struct.readm %arg0[@adv_0_4] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %41, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %42 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %43 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %42, %43 : !felt.type<"bn254">, !felt.type<"bn254"> + %44 = struct.readm %arg0[@adv_1_2] : <@Main<[]>>, !felt.type<"bn254"> + %45 = struct.readm %arg0[@out_1] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %44, %45 : !felt.type<"bn254">, !felt.type<"bn254"> + %46 = struct.readm %arg0[@adv_1_4] : <@Main<[]>>, !felt.type<"bn254"> + %47 = struct.readm %arg0[@out_2] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %46, %47 : !felt.type<"bn254">, !felt.type<"bn254"> + %48 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %felt_const_1000 = felt.const 1000 <"bn254"> + %49 = bool.cmp lt(%48, %felt_const_1000) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %49 + %50 = struct.readm %arg0[@adv_0_1] : <@Main<[]>>, !felt.type<"bn254"> + %felt_const_1000_12 = felt.const 1000 <"bn254"> + %51 = bool.cmp ge(%50, %felt_const_1000_12) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %51 + %52 = struct.readm %arg0[@adv_0_2] : <@Main<[]>>, !felt.type<"bn254"> + %felt_const_1000_13 = felt.const 1000 <"bn254"> + %53 = bool.cmp lt(%52, %felt_const_1000_13) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %53 + %54 = struct.readm %arg0[@adv_0_3] : <@Main<[]>>, !felt.type<"bn254"> + %felt_const_1000_14 = felt.const 1000 <"bn254"> + %55 = bool.cmp ge(%54, %felt_const_1000_14) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %55 + %56 = struct.readm %arg0[@adv_0_4] : <@Main<[]>>, !felt.type<"bn254"> + %felt_const_1000_15 = felt.const 1000 <"bn254"> + %57 = bool.cmp lt(%56, %felt_const_1000_15) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %57 + %58 = struct.readm %arg0[@adv_0_5] : <@Main<[]>>, !felt.type<"bn254"> + %felt_const_1000_16 = felt.const 1000 <"bn254"> + %59 = bool.cmp ge(%58, %felt_const_1000_16) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %59 + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_0_2 : !felt.type<"bn254"> + struct.member @adv_0_3 : !felt.type<"bn254"> + struct.member @adv_1_2 : !felt.type<"bn254"> + struct.member @adv_0_4 : !felt.type<"bn254"> + struct.member @adv_0_5 : !felt.type<"bn254"> + struct.member @adv_1_4 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/mul_inject_opt.mlir b/driver/tests/expected/llzk/mul_inject_opt.mlir new file mode 100644 index 0000000..7d064f9 --- /dev/null +++ b/driver/tests/expected/llzk/mul_inject_opt.mlir @@ -0,0 +1,66 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_1 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_2 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1000 = felt.const 1000 <"bn254"> + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.neg %0 : !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_0_1] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = felt.mul %0, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %3, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = struct.readm %arg0[@adv_0_2] : <@Main<[]>>, !felt.type<"bn254"> + %6 = felt.neg %5 : !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_0_3] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %8 = felt.mul %5, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@adv_1_2] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %8, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@adv_0_4] : <@Main<[]>>, !felt.type<"bn254"> + %11 = felt.neg %10 : !felt.type<"bn254"> + %12 = struct.readm %arg0[@adv_0_5] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %11, %12 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = felt.mul %10, %12 : !felt.type<"bn254">, !felt.type<"bn254"> + %14 = struct.readm %arg0[@adv_1_4] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %13, %14 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %5, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %10, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %15 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %4, %15 : !felt.type<"bn254">, !felt.type<"bn254"> + %16 = struct.readm %arg0[@out_1] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %9, %16 : !felt.type<"bn254">, !felt.type<"bn254"> + %17 = struct.readm %arg0[@out_2] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %14, %17 : !felt.type<"bn254">, !felt.type<"bn254"> + %18 = bool.cmp lt(%0, %felt_const_1000) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %18 + %19 = bool.cmp ge(%2, %felt_const_1000) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %19 + %20 = bool.cmp lt(%5, %felt_const_1000) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %20 + %21 = bool.cmp ge(%7, %felt_const_1000) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %21 + %22 = bool.cmp lt(%10, %felt_const_1000) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %22 + %23 = bool.cmp ge(%12, %felt_const_1000) : !felt.type<"bn254">, !felt.type<"bn254"> + bool.assert %23 + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_0_2 : !felt.type<"bn254"> + struct.member @adv_0_3 : !felt.type<"bn254"> + struct.member @adv_1_2 : !felt.type<"bn254"> + struct.member @adv_0_4 : !felt.type<"bn254"> + struct.member @adv_0_5 : !felt.type<"bn254"> + struct.member @adv_1_4 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/mul_with_fixed_constraint.mlir b/driver/tests/expected/llzk/mul_with_fixed_constraint.mlir new file mode 100644 index 0000000..552b1f9 --- /dev/null +++ b/driver/tests/expected/llzk/mul_with_fixed_constraint.mlir @@ -0,0 +1,57 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %3 = felt.neg %2 : !felt.type<"bn254"> + %4 = felt.add %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = felt.mul %felt_const_1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %5, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %6 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %8 = felt.mul %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %10 = felt.neg %9 : !felt.type<"bn254"> + %11 = felt.add %8, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = felt.mul %felt_const_1_0, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %12, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_2 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616_3 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %felt_const_2 = felt.const 2 <"bn254"> + %13 = felt.neg %felt_const_2 : !felt.type<"bn254"> + %14 = felt.add %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616_3, %13 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_3 = felt.const 3 <"bn254"> + %15 = felt.add %14, %felt_const_3 : !felt.type<"bn254">, !felt.type<"bn254"> + %16 = felt.mul %felt_const_1_2, %15 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_4 = felt.const 0 <"bn254"> + constrain.eq %16, %felt_const_0_4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_2_5 = felt.const 2 <"bn254"> + %17 = struct.readm %arg0[@adv_3_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %felt_const_2_5, %17 : !felt.type<"bn254">, !felt.type<"bn254"> + %18 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %18, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %19 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %20 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %19, %20 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_2_6 = felt.const 2 <"bn254"> + %felt_const_2_7 = felt.const 2 <"bn254"> + constrain.eq %felt_const_2_6, %felt_const_2_7 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + struct.member @adv_3_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/mul_with_fixed_constraint_opt.mlir b/driver/tests/expected/llzk/mul_with_fixed_constraint_opt.mlir new file mode 100644 index 0000000..10f4980 --- /dev/null +++ b/driver/tests/expected/llzk/mul_with_fixed_constraint_opt.mlir @@ -0,0 +1,29 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_2 = felt.const 2 <"bn254"> + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.neg %0 : !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = felt.mul %0, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %3, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = struct.readm %arg0[@adv_3_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %5, %felt_const_2 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %4, %6 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + struct.member @adv_3_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/mul_with_rewriter.mlir b/driver/tests/expected/llzk/mul_with_rewriter.mlir new file mode 100644 index 0000000..dbb7d95 --- /dev/null +++ b/driver/tests/expected/llzk/mul_with_rewriter.mlir @@ -0,0 +1,40 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %3 = felt.neg %2 : !felt.type<"bn254"> + %4 = felt.add %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = felt.mul %felt_const_1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %5, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %6 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %8 = felt.mul %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %10 = felt.neg %9 : !felt.type<"bn254"> + %11 = felt.add %8, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = felt.mul %felt_const_1_0, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %12, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %13, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %14 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %15 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %14, %15 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/mul_with_rewriter_opt.mlir b/driver/tests/expected/llzk/mul_with_rewriter_opt.mlir new file mode 100644 index 0000000..34cf0c4 --- /dev/null +++ b/driver/tests/expected/llzk/mul_with_rewriter_opt.mlir @@ -0,0 +1,25 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.neg %0 : !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = felt.mul %0, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %3, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %4, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/recursive_groups.mlir b/driver/tests/expected/llzk/recursive_groups.mlir new file mode 100644 index 0000000..6224101 --- /dev/null +++ b/driver/tests/expected/llzk/recursive_groups.mlir @@ -0,0 +1,135 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @mul_many { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">, %arg1: !felt.type<"bn254">) -> !struct.type<@mul_many<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@mul_many<[]>> + function.return %self : !struct.type<@mul_many<[]>> + } + function.def @constrain(%arg0: !struct.type<@mul_many<[]>>, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %0 = struct.readm %arg0[@adv_0_4] : <@mul_many<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_4] : <@mul_many<[]>>, !felt.type<"bn254"> + %2 = felt.mul %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@out_0] : <@mul_many<[]>>, !felt.type<"bn254"> + %4 = felt.neg %3 : !felt.type<"bn254"> + %5 = felt.add %2, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = felt.mul %felt_const_1, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %6, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_0_4] : <@mul_many<[]>>, !felt.type<"bn254"> + constrain.eq %arg1, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %8 = struct.readm %arg0[@adv_1_4] : <@mul_many<[]>>, !felt.type<"bn254"> + constrain.eq %arg2, %8 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_4 : !felt.type<"bn254"> + struct.member @adv_1_4 : !felt.type<"bn254"> + } + struct.def @mul_many1 { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">) -> !struct.type<@mul_many1<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@mul_many1<[]>> + function.return %self : !struct.type<@mul_many1<[]>> + } + function.def @constrain(%arg0: !struct.type<@mul_many1<[]>>, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">, %arg3: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@mul_many_0] : <@mul_many1<[]>>, !struct.type<@mul_many<[]>> + function.call @mul_many::@constrain(%0, %arg2, %arg3) : (!struct.type<@mul_many<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %1 = struct.readm %arg0[@adv_2_4] : <@mul_many1<[]>>, !felt.type<"bn254"> + %2 = struct.readm %arg0[@mul_many_0] : <@mul_many1<[]>>, !struct.type<@mul_many<[]>> + %3 = struct.readm %2[@out_0] : <@mul_many<[]>>, !felt.type<"bn254"> + constrain.eq %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1 = felt.const 1 <"bn254"> + %4 = struct.readm %arg0[@adv_0_5] : <@mul_many1<[]>>, !felt.type<"bn254"> + %5 = struct.readm %arg0[@adv_1_5] : <@mul_many1<[]>>, !felt.type<"bn254"> + %6 = felt.mul %4, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@out_0] : <@mul_many1<[]>>, !felt.type<"bn254"> + %8 = felt.neg %7 : !felt.type<"bn254"> + %9 = felt.add %6, %8 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = felt.mul %felt_const_1, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %10, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %11 = struct.readm %arg0[@adv_0_5] : <@mul_many1<[]>>, !felt.type<"bn254"> + constrain.eq %arg1, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = struct.readm %arg0[@adv_2_4] : <@mul_many1<[]>>, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_1_5] : <@mul_many1<[]>>, !felt.type<"bn254"> + constrain.eq %12, %13 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @mul_many_0 : !struct.type<@mul_many<[]>> + struct.member @adv_2_4 : !felt.type<"bn254"> + struct.member @adv_0_5 : !felt.type<"bn254"> + struct.member @adv_1_5 : !felt.type<"bn254"> + } + struct.def @mul_many2 { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">, %arg3: !felt.type<"bn254">) -> !struct.type<@mul_many2<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@mul_many2<[]>> + function.return %self : !struct.type<@mul_many2<[]>> + } + function.def @constrain(%arg0: !struct.type<@mul_many2<[]>>, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">, %arg3: !felt.type<"bn254">, %arg4: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@mul_many1_0] : <@mul_many2<[]>>, !struct.type<@mul_many1<[]>> + function.call @mul_many1::@constrain(%0, %arg2, %arg3, %arg4) : (!struct.type<@mul_many1<[]>>, !felt.type<"bn254">, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %1 = struct.readm %arg0[@adv_2_5] : <@mul_many2<[]>>, !felt.type<"bn254"> + %2 = struct.readm %arg0[@mul_many1_0] : <@mul_many2<[]>>, !struct.type<@mul_many1<[]>> + %3 = struct.readm %2[@out_0] : <@mul_many1<[]>>, !felt.type<"bn254"> + constrain.eq %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1 = felt.const 1 <"bn254"> + %4 = struct.readm %arg0[@adv_0_6] : <@mul_many2<[]>>, !felt.type<"bn254"> + %5 = struct.readm %arg0[@adv_1_6] : <@mul_many2<[]>>, !felt.type<"bn254"> + %6 = felt.mul %4, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@out_0] : <@mul_many2<[]>>, !felt.type<"bn254"> + %8 = felt.neg %7 : !felt.type<"bn254"> + %9 = felt.add %6, %8 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = felt.mul %felt_const_1, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %10, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %11 = struct.readm %arg0[@adv_0_6] : <@mul_many2<[]>>, !felt.type<"bn254"> + constrain.eq %arg1, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = struct.readm %arg0[@adv_2_5] : <@mul_many2<[]>>, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_1_6] : <@mul_many2<[]>>, !felt.type<"bn254"> + constrain.eq %12, %13 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @mul_many1_0 : !struct.type<@mul_many1<[]>> + struct.member @adv_2_5 : !felt.type<"bn254"> + struct.member @adv_0_6 : !felt.type<"bn254"> + struct.member @adv_1_6 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg3: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg3: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg4: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_0_1] : <@Main<[]>>, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_0_2] : <@Main<[]>>, !felt.type<"bn254"> + %3 = struct.readm %arg0[@adv_0_3] : <@Main<[]>>, !felt.type<"bn254"> + %4 = struct.readm %arg0[@mul_many2_0] : <@Main<[]>>, !struct.type<@mul_many2<[]>> + function.call @mul_many2::@constrain(%4, %0, %1, %2, %3) : (!struct.type<@mul_many2<[]>>, !felt.type<"bn254">, !felt.type<"bn254">, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %5 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + %6 = struct.readm %arg0[@mul_many2_0] : <@Main<[]>>, !struct.type<@mul_many2<[]>> + %7 = struct.readm %6[@out_0] : <@mul_many2<[]>>, !felt.type<"bn254"> + constrain.eq %5, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %8 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %8, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@adv_0_1] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %9, %arg2 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@adv_0_2] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %10, %arg3 : !felt.type<"bn254">, !felt.type<"bn254"> + %11 = struct.readm %arg0[@adv_0_3] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %11, %arg4 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + %13 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %12, %13 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_0_2 : !felt.type<"bn254"> + struct.member @adv_0_3 : !felt.type<"bn254"> + struct.member @mul_many2_0 : !struct.type<@mul_many2<[]>> + struct.member @adv_2_6 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/recursive_groups_opt.mlir b/driver/tests/expected/llzk/recursive_groups_opt.mlir new file mode 100644 index 0000000..faa7354 --- /dev/null +++ b/driver/tests/expected/llzk/recursive_groups_opt.mlir @@ -0,0 +1,104 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @mul_many { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">, %arg1: !felt.type<"bn254">) -> !struct.type<@mul_many<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@mul_many<[]>> + function.return %self : !struct.type<@mul_many<[]>> + } + function.def @constrain(%arg0: !struct.type<@mul_many<[]>>, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_4] : <@mul_many<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_1_4] : <@mul_many<[]>>, !felt.type<"bn254"> + %2 = felt.mul %0, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@out_0] : <@mul_many<[]>>, !felt.type<"bn254"> + constrain.eq %2, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %arg1, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %arg2, %1 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_4 : !felt.type<"bn254"> + struct.member @adv_1_4 : !felt.type<"bn254"> + } + struct.def @mul_many1 { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">) -> !struct.type<@mul_many1<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@mul_many1<[]>> + function.return %self : !struct.type<@mul_many1<[]>> + } + function.def @constrain(%arg0: !struct.type<@mul_many1<[]>>, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">, %arg3: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@mul_many_0] : <@mul_many1<[]>>, !struct.type<@mul_many<[]>> + function.call @mul_many::@constrain(%0, %arg2, %arg3) : (!struct.type<@mul_many<[]>>, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %1 = struct.readm %arg0[@adv_2_4] : <@mul_many1<[]>>, !felt.type<"bn254"> + %2 = struct.readm %0[@out_0] : <@mul_many<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@adv_0_5] : <@mul_many1<[]>>, !felt.type<"bn254"> + %4 = struct.readm %arg0[@adv_1_5] : <@mul_many1<[]>>, !felt.type<"bn254"> + %5 = felt.mul %3, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = struct.readm %arg0[@out_0] : <@mul_many1<[]>>, !felt.type<"bn254"> + constrain.eq %5, %6 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %arg1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @mul_many_0 : !struct.type<@mul_many<[]>> + struct.member @adv_2_4 : !felt.type<"bn254"> + struct.member @adv_0_5 : !felt.type<"bn254"> + struct.member @adv_1_5 : !felt.type<"bn254"> + } + struct.def @mul_many2 { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">, %arg3: !felt.type<"bn254">) -> !struct.type<@mul_many2<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@mul_many2<[]>> + function.return %self : !struct.type<@mul_many2<[]>> + } + function.def @constrain(%arg0: !struct.type<@mul_many2<[]>>, %arg1: !felt.type<"bn254">, %arg2: !felt.type<"bn254">, %arg3: !felt.type<"bn254">, %arg4: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@mul_many1_0] : <@mul_many2<[]>>, !struct.type<@mul_many1<[]>> + function.call @mul_many1::@constrain(%0, %arg2, %arg3, %arg4) : (!struct.type<@mul_many1<[]>>, !felt.type<"bn254">, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %1 = struct.readm %arg0[@adv_2_5] : <@mul_many2<[]>>, !felt.type<"bn254"> + %2 = struct.readm %0[@out_0] : <@mul_many1<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = struct.readm %arg0[@adv_0_6] : <@mul_many2<[]>>, !felt.type<"bn254"> + %4 = struct.readm %arg0[@adv_1_6] : <@mul_many2<[]>>, !felt.type<"bn254"> + %5 = felt.mul %3, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %6 = struct.readm %arg0[@out_0] : <@mul_many2<[]>>, !felt.type<"bn254"> + constrain.eq %5, %6 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %arg1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @mul_many1_0 : !struct.type<@mul_many1<[]>> + struct.member @adv_2_5 : !felt.type<"bn254"> + struct.member @adv_0_6 : !felt.type<"bn254"> + struct.member @adv_1_6 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg3: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg3: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg4: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@adv_0_1] : <@Main<[]>>, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_0_2] : <@Main<[]>>, !felt.type<"bn254"> + %3 = struct.readm %arg0[@adv_0_3] : <@Main<[]>>, !felt.type<"bn254"> + %4 = struct.readm %arg0[@mul_many2_0] : <@Main<[]>>, !struct.type<@mul_many2<[]>> + function.call @mul_many2::@constrain(%4, %0, %1, %2, %3) : (!struct.type<@mul_many2<[]>>, !felt.type<"bn254">, !felt.type<"bn254">, !felt.type<"bn254">, !felt.type<"bn254">) -> () + %5 = struct.readm %arg0[@adv_2_6] : <@Main<[]>>, !felt.type<"bn254"> + %6 = struct.readm %4[@out_0] : <@mul_many2<[]>>, !felt.type<"bn254"> + constrain.eq %5, %6 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %1, %arg2 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %2, %arg3 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %3, %arg4 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %5, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_0_2 : !felt.type<"bn254"> + struct.member @adv_0_3 : !felt.type<"bn254"> + struct.member @mul_many2_0 : !struct.type<@mul_many2<[]>> + struct.member @adv_2_6 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/same_body.mlir b/driver/tests/expected/llzk/same_body.mlir new file mode 100644 index 0000000..5f28117 --- /dev/null +++ b/driver/tests/expected/llzk/same_body.mlir @@ -0,0 +1,74 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @"test group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"test group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group"<[]>> + function.return %self : !struct.type<@"test group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %0 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %1 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %3 = felt.neg %2 : !felt.type<"bn254"> + %4 = felt.add %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = felt.mul %felt_const_1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %5, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %6 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_1_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %8 = felt.mul %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + %10 = felt.neg %9 : !felt.type<"bn254"> + %11 = felt.add %8, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = felt.mul %felt_const_1_0, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %12, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %arg1, %13 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_1 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%1, %0) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %2 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %3 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + %4 = struct.readm %3[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %2, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %6 = struct.readm %arg0[@"test group_1"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%6, %5) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %7 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %8 = struct.readm %arg0[@"test group_1"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + %9 = struct.readm %8[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %7, %9 : !felt.type<"bn254">, !felt.type<"bn254"> + %10 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %10, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %11 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %12 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %11, %12 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + %14 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %13, %14 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @"test group_0" : !struct.type<@"test group"<[]>> + struct.member @adv_2_1 : !felt.type<"bn254"> + struct.member @"test group_1" : !struct.type<@"test group"<[]>> + struct.member @adv_2_2 : !felt.type<"bn254"> + struct.member @adv_2_3 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/same_body_opt.mlir b/driver/tests/expected/llzk/same_body_opt.mlir new file mode 100644 index 0000000..97d94ea --- /dev/null +++ b/driver/tests/expected/llzk/same_body_opt.mlir @@ -0,0 +1,54 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @"test group" { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254">) -> !struct.type<@"test group"<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@"test group"<[]>> + function.return %self : !struct.type<@"test group"<[]>> + } + function.def @constrain(%arg0: !struct.type<@"test group"<[]>>, %arg1: !felt.type<"bn254">) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_1] : <@"test group"<[]>>, !felt.type<"bn254"> + %1 = felt.neg %0 : !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_1] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = felt.mul %0, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %3, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %arg1, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_1 : !felt.type<"bn254"> + struct.member @adv_1_1 : !felt.type<"bn254"> + } + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = struct.readm %arg0[@"test group_0"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%1, %0) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %2 = struct.readm %arg0[@adv_2_1] : <@Main<[]>>, !felt.type<"bn254"> + %3 = struct.readm %1[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %2, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@"test group_1"] : <@Main<[]>>, !struct.type<@"test group"<[]>> + function.call @"test group"::@constrain(%4, %2) : (!struct.type<@"test group"<[]>>, !felt.type<"bn254">) -> () + %5 = struct.readm %arg0[@adv_2_2] : <@Main<[]>>, !felt.type<"bn254"> + %6 = struct.readm %4[@out_0] : <@"test group"<[]>>, !felt.type<"bn254"> + constrain.eq %5, %6 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_2_3] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %5, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %8 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %7, %8 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @"test group_0" : !struct.type<@"test group"<[]>> + struct.member @adv_2_1 : !felt.type<"bn254"> + struct.member @"test group_1" : !struct.type<@"test group"<[]>> + struct.member @adv_2_2 : !felt.type<"bn254"> + struct.member @adv_2_3 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/ten_plus_io.mlir b/driver/tests/expected/llzk/ten_plus_io.mlir new file mode 100644 index 0000000..6a7f2f8 --- /dev/null +++ b/driver/tests/expected/llzk/ten_plus_io.mlir @@ -0,0 +1,50 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_1 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_2 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_3 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_4 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_5 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_6 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_7 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_8 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_9 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_10 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg3: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg4: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg5: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg6: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg7: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg8: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg9: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg10: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg3: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg4: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg5: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg6: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg7: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg8: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg9: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg10: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg11: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %felt_const_1 = felt.const 1 <"bn254"> + %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 <"bn254"> + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.mul %felt_const_21888242871839275222246405745257275088548364400416034343698204186575808495616, %0 : !felt.type<"bn254">, !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %3 = felt.neg %2 : !felt.type<"bn254"> + %4 = felt.add %1, %3 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = felt.mul %felt_const_1, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0 = felt.const 0 <"bn254"> + constrain.eq %5, %felt_const_0 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_1_0 = felt.const 1 <"bn254"> + %6 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %7 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + %8 = felt.mul %6, %7 : !felt.type<"bn254">, !felt.type<"bn254"> + %9 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %10 = felt.neg %9 : !felt.type<"bn254"> + %11 = felt.add %8, %10 : !felt.type<"bn254">, !felt.type<"bn254"> + %12 = felt.mul %felt_const_1_0, %11 : !felt.type<"bn254">, !felt.type<"bn254"> + %felt_const_0_1 = felt.const 0 <"bn254"> + constrain.eq %12, %felt_const_0_1 : !felt.type<"bn254">, !felt.type<"bn254"> + %13 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %13, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %14 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + %15 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %14, %15 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/expected/llzk/ten_plus_io_opt.mlir b/driver/tests/expected/llzk/ten_plus_io_opt.mlir new file mode 100644 index 0000000..162704a --- /dev/null +++ b/driver/tests/expected/llzk/ten_plus_io_opt.mlir @@ -0,0 +1,35 @@ +module attributes { llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>> } { + struct.def @Main { + struct.member @out_0 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_1 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_2 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_3 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_4 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_5 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_6 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_7 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_8 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_9 : !felt.type<"bn254"> {llzk.pub} + struct.member @out_10 : !felt.type<"bn254"> {llzk.pub} + function.def @compute(%arg0: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg3: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg4: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg5: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg6: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg7: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg8: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg9: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg10: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { + %self = struct.new : <@Main<[]>> + function.return %self : !struct.type<@Main<[]>> + } + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg2: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg3: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg4: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg5: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg6: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg7: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg8: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg9: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg10: !felt.type<"bn254"> {llzk.pub = #llzk.pub}, %arg11: !felt.type<"bn254"> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + %0 = struct.readm %arg0[@adv_0_0] : <@Main<[]>>, !felt.type<"bn254"> + %1 = felt.neg %0 : !felt.type<"bn254"> + %2 = struct.readm %arg0[@adv_1_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %1, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %3 = felt.mul %0, %2 : !felt.type<"bn254">, !felt.type<"bn254"> + %4 = struct.readm %arg0[@adv_2_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %3, %4 : !felt.type<"bn254">, !felt.type<"bn254"> + constrain.eq %0, %arg1 : !felt.type<"bn254">, !felt.type<"bn254"> + %5 = struct.readm %arg0[@out_0] : <@Main<[]>>, !felt.type<"bn254"> + constrain.eq %4, %5 : !felt.type<"bn254">, !felt.type<"bn254"> + function.return + } + struct.member @adv_0_0 : !felt.type<"bn254"> + struct.member @adv_1_0 : !felt.type<"bn254"> + struct.member @adv_2_0 : !felt.type<"bn254"> + } +} diff --git a/driver/tests/tests/expected/picus/mul_with_fixed_constraint.picus b/driver/tests/expected/picus/mul_with_fixed_constraint_zcash.picus similarity index 100% rename from driver/tests/tests/expected/picus/mul_with_fixed_constraint.picus rename to driver/tests/expected/picus/mul_with_fixed_constraint_zcash.picus index 63bbfdf..f47b570 100644 --- a/driver/tests/tests/expected/picus/mul_with_fixed_constraint.picus +++ b/driver/tests/expected/picus/mul_with_fixed_constraint_zcash.picus @@ -5,8 +5,8 @@ (assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_0) (- adv_1_0))) 0)) (assert (= (* 1 (+ (* adv_0_0 adv_1_0) (- adv_2_0))) 0)) (assert (= (* 1 (+ (+ 21888242871839275222246405745257275088548364400416034343698204186575808495616 (- 2)) 3)) 0)) -(assert (= 2 adv_3_0)) (assert (= adv_0_0 in_0)) +(assert (= 2 adv_3_0)) (assert (= adv_2_0 out_0)) (assert (= 2 2)) (end-module) diff --git a/driver/tests/common/llzk.rs b/driver/tests/mdnt_common/llzk.rs similarity index 74% rename from driver/tests/common/llzk.rs rename to driver/tests/mdnt_common/llzk.rs index 5ea20b5..ed7840a 100644 --- a/driver/tests/common/llzk.rs +++ b/driver/tests/mdnt_common/llzk.rs @@ -2,23 +2,28 @@ mod inner { use ff::PrimeField; use haloumi::{ - driver::Driver, ir_gen::IRGenParams, ir_gen::circuit::resolved::ResolvedIRCircuit, + driver::Driver, ir::r#gen::IRGenParams, ir::r#gen::circuit::resolved::ResolvedIRCircuit, synthesis::CircuitSynthesis, }; use haloumi_llzk::LlzkParams; use haloumi_midnight_integration::plonk::{_Expression, ConstraintSystem}; use llzk::prelude::{LlzkContext, OperationLike as _}; - use crate::common::common_lowering; + use crate::mdnt_common::common_lowering; #[allow(dead_code)] pub fn llzk_params(ctx: &LlzkContext) -> LlzkParams<'_> { - LlzkParams::new(ctx).no_optimize() + LlzkParams::new(ctx) + .no_optimize() + // The field is named `halo2curves::bn256` but LLZK uses the bn254 name instead. + .with_builtin_field("bn254") } #[allow(dead_code)] pub fn opt_llzk_params(ctx: &LlzkContext) -> LlzkParams<'_> { LlzkParams::new(ctx) + // The field is named `halo2curves::bn256` but LLZK uses the bn254 name instead. + .with_builtin_field("bn254") } #[allow(dead_code)] @@ -63,15 +68,15 @@ macro_rules! basic_llzk_test { ($name:ident, $circuit:expr, $expected:expr, $expected_opt:expr, $ir_params:expr $(,)?) => { paste::paste! { #[cfg(feature = "llzk-backend")] - mod [< $name _llzk >] { + mod [] { use super::*; #[test] fn no_opt() { - common::setup(); + mdnt_common::setup(); let ctx = llzk::context::LlzkContext::new(); - common::llzk::llzk_test( + mdnt_common::llzk::llzk_test( $circuit, - common::llzk::llzk_params(&ctx), + mdnt_common::llzk::llzk_params(&ctx), $ir_params, $expected, false, @@ -80,11 +85,11 @@ macro_rules! basic_llzk_test { #[test] fn opt() { - common::setup(); + mdnt_common::setup(); let ctx = llzk::context::LlzkContext::new(); - common::llzk::llzk_test( + mdnt_common::llzk::llzk_test( $circuit, - common::llzk::opt_llzk_params(&ctx), + mdnt_common::llzk::opt_llzk_params(&ctx), $ir_params, $expected_opt, true, @@ -93,13 +98,13 @@ macro_rules! basic_llzk_test { } } }; - ($name:ident, $circuit:expr, $expected:expr, $expected_opt:expr $(,)?) => { - $crate::common::llzk::basic_llzk_test! { + ($name:ident, $circuit:expr, $expected:expr, $expected_opt:expr, $(,)?) => { + $crate::mdnt_common::llzk::basic_llzk_test! { $name, $circuit, $expected, $expected_opt, - haloumi::ir_gen::IRGenParams::new() + haloumi::ir::r#gen::IRGenParams::new() } }; } diff --git a/driver/tests/common/mod.rs b/driver/tests/mdnt_common/mod.rs similarity index 81% rename from driver/tests/common/mod.rs rename to driver/tests/mdnt_common/mod.rs index 2ddda0a..67c6c91 100644 --- a/driver/tests/common/mod.rs +++ b/driver/tests/mdnt_common/mod.rs @@ -1,8 +1,8 @@ use ff::{Field, PrimeField}; use haloumi::{ driver::Driver, - ir_gen::gates::{GateScope, callbacks::GateCallbacks, rewrite::GateRewritePattern}, - ir_gen::{IRGenParams, circuit::resolved::ResolvedIRCircuit}, + ir::r#gen::gates::{GateScope, callbacks::GateCallbacks, rewrite::GateRewritePattern}, + ir::r#gen::{IRGenParams, circuit::resolved::ResolvedIRCircuit}, synthesis::CircuitSynthesis, }; use haloumi_ir_gen::gates::rewrite::{Match, MatchResult}; @@ -169,3 +169,33 @@ macro_rules! synthesis_impl { } pub(crate) use synthesis_impl; + +macro_rules! basic_test { + ($name:ident, $circuit:expr, $expected:expr, $expected_opt:expr, $ir_params:expr $(,)?) => { + $crate::mdnt_common::picus::basic_picus_test! { + $name, + $circuit, + include_str!(concat!("expected/picus/", $expected, ".picus")), + include_str!(concat!("expected/picus/", $expected_opt, ".picus")), + $ir_params + } + $crate::mdnt_common::llzk::basic_llzk_test! { + $name, + $circuit, + include_str!(concat!("expected/llzk/", $expected, ".mlir")), + include_str!(concat!("expected/llzk/", $expected_opt, ".mlir")), + $ir_params + } + }; + ($name:ident, $circuit:expr, $expected:expr, $expected_opt:expr $(,)?) => { + $crate::mdnt_common::basic_test! { + $name, + $circuit, + $expected, + $expected_opt, + haloumi::ir::r#gen::IRGenParams::new() + } + }; +} + +pub(crate) use basic_test; diff --git a/driver/tests/common/picus.rs b/driver/tests/mdnt_common/picus.rs similarity index 80% rename from driver/tests/common/picus.rs rename to driver/tests/mdnt_common/picus.rs index 490389e..3fb7beb 100644 --- a/driver/tests/common/picus.rs +++ b/driver/tests/mdnt_common/picus.rs @@ -1,9 +1,9 @@ #[cfg(feature = "picus-backend")] mod inner { - use crate::common::{clean_string, common_lowering}; + use crate::mdnt_common::{clean_string, common_lowering}; use ff::PrimeField; use haloumi::{ - driver::Driver, ir_gen::IRGenParams, ir_gen::circuit::resolved::ResolvedIRCircuit, + driver::Driver, ir::r#gen::IRGenParams, ir::r#gen::circuit::resolved::ResolvedIRCircuit, synthesis::CircuitSynthesis, }; use haloumi_midnight_integration::plonk::{_Expression, ConstraintSystem}; @@ -55,14 +55,14 @@ macro_rules! basic_picus_test { ($name:ident, $circuit:expr, $expected:expr, $expected_opt:expr, $ir_params:expr $(,)?) => { paste::paste! { #[cfg(feature = "picus-backend")] - mod [< $name _picus >] { + mod [] { use super::*; #[test] fn no_opt() { - common::setup(); - common::picus::picus_test( + mdnt_common::setup(); + mdnt_common::picus::picus_test( $circuit, - common::picus::picus_params(), + mdnt_common::picus::picus_params(), $ir_params, $expected, false, @@ -71,10 +71,10 @@ macro_rules! basic_picus_test { #[test] fn opt() { - common::setup(); - common::picus::picus_test( + mdnt_common::setup(); + mdnt_common::picus::picus_test( $circuit, - common::picus::opt_picus_params(), + mdnt_common::picus::opt_picus_params(), $ir_params, $expected_opt, true, @@ -84,12 +84,12 @@ macro_rules! basic_picus_test { } }; ($name:ident, $circuit:expr, $expected:expr, $expected_opt:expr $(,)?) => { - $crate::common::picus::basic_picus_test! { + $crate::mdnt_common::picus::basic_picus_test! { $name, $circuit, $expected, $expected_opt, - haloumi::ir_gen::IRGenParams::new() + haloumi::ir::r#gen::IRGenParams::new() } }; } diff --git a/driver/tests/fibonacci_tests.rs b/driver/tests/mdnt_fibonacci_tests.rs similarity index 52% rename from driver/tests/fibonacci_tests.rs rename to driver/tests/mdnt_fibonacci_tests.rs index 71bd14d..651a271 100644 --- a/driver/tests/fibonacci_tests.rs +++ b/driver/tests/mdnt_fibonacci_tests.rs @@ -1,21 +1,21 @@ -use common::{picus::basic_picus_test, synthesis_impl}; use halo2curves::bn256::Fr; -use haloumi_test_circuits::fibonacci; +use haloumi_mdnt_test_circuits::fibonacci; +use mdnt_common::{basic_test, synthesis_impl}; -mod common; +mod mdnt_common; -basic_picus_test! { +basic_test! { fibonacci_circuit, FibonacciCircuitSynthesis::default(), - include_str!("expected/picus/fibonacci.picus"), - include_str!("expected/picus/fibonacci_opt.picus") + "fibonacci", + "fibonacci_opt", } -basic_picus_test! { +basic_test! { fibonacci_grouped_circuit, GroupedFibonacciCircuitSynthesis::default(), - include_str!("expected/picus/fibonacci_grouped.picus"), - include_str!("expected/picus/fibonacci_grouped_opt.picus") + "fibonacci_grouped", + "fibonacci_grouped_opt", } synthesis_impl!( diff --git a/driver/tests/tests/lookup_tests.rs b/driver/tests/mdnt_lookup_tests.rs similarity index 54% rename from driver/tests/tests/lookup_tests.rs rename to driver/tests/mdnt_lookup_tests.rs index 49d08bd..5c3df1d 100644 --- a/driver/tests/tests/lookup_tests.rs +++ b/driver/tests/mdnt_lookup_tests.rs @@ -1,59 +1,56 @@ -#[cfg(feature = "picus-backend")] -use common::picus::basic_picus_test; -use common::synthesis_impl; use group::ff::Field; -use halo2_llzk_frontend::{ - LookupCallbacks, - ir::generate::IRGenParamsBuilder, - lookups::{Lookup, table::LookupTableGenerator}, - temps::{ExprOrTemp, Temps}, -}; -use halo2_midnight_integration::plonk::_Expression; -use halo2_test_circuits::lookup; use halo2curves::bn256::Fr; +use haloumi::{ + ir::r#gen::IRGenParams, + ir::r#gen::lookups::callbacks::LookupCallbacks, + ir::r#gen::lookups::table::LookupTableGenerator, + ir::r#gen::temps::{ExprOrTemp, Temps}, + synthesis::lookups::Lookup, +}; use haloumi_ir::stmt::IRStmt; +use haloumi_ir_gen::lookups::callbacks::LookupError; +use haloumi_mdnt_test_circuits::lookup; +use haloumi_midnight_integration::plonk::_Expression; +use mdnt_common::basic_test; +use mdnt_common::synthesis_impl; use std::borrow::Cow; -mod common; +mod mdnt_common; -basic_picus_test! { +basic_test! { lookup_circuit, LookupCircuitSynthesis::default(), - include_str!("expected/picus/lookup.picus"), - include_str!("expected/picus/lookup_opt.picus"), - IRGenParamsBuilder::new() + "lookup", + "lookup_opt", + IRGenParams::new() .lookup_callbacks(&LookupCallbackHandler) - .build() } -basic_picus_test! { +basic_test! { lookup_2x3_circuit, Lookup2x3CircuitSynthesis::default(), - include_str!("expected/picus/lookup_2x3.picus"), - include_str!("expected/picus/lookup_2x3_opt.picus"), - IRGenParamsBuilder::new() + "lookup_2x3", + "lookup_2x3_opt", + IRGenParams::new() .lookup_callbacks(&LookupCallbackHandler) - .build(), } -basic_picus_test! { +basic_test! { lookup_2x3_fixed_circuit, Lookup2x3FixedCircuitSynthesis::default(), - include_str!("expected/picus/lookup_2x3.picus"), - include_str!("expected/picus/lookup_2x3_opt.picus"), - IRGenParamsBuilder::new() + "lookup_2x3", + "lookup_2x3_opt", + IRGenParams::new() .lookup_callbacks(&LookupCallbackHandler) - .build(), } -basic_picus_test! { +basic_test! { lookup_2x3_zerosel_circuit, Lookup2x3ZeroSelCircuitSynthesis::default(), - include_str!("expected/picus/lookup_2x3.picus"), - include_str!("expected/picus/lookup_2x3_opt.picus"), - IRGenParamsBuilder::new() + "lookup_2x3", + "lookup_2x3_opt", + IRGenParams::new() .lookup_callbacks(&LookupCallbackHandler) - .build(), } synthesis_impl!(LookupCircuitSynthesis, lookup::LookupCircuit, [0], [1]); @@ -84,7 +81,7 @@ impl LookupCallbacks> for LookupCallbackHandler { _lookup: &'a Lookup<_Expression>, _table: &dyn LookupTableGenerator, _temps: &mut Temps, - ) -> anyhow::Result>>>> { + ) -> Result>>>, LookupError> { Ok(IRStmt::comment("Ignored lookup")) } } diff --git a/driver/tests/tests/mul_tests.rs b/driver/tests/mdnt_mul_tests.rs similarity index 57% rename from driver/tests/tests/mul_tests.rs rename to driver/tests/mdnt_mul_tests.rs index 3558196..774309a 100644 --- a/driver/tests/tests/mul_tests.rs +++ b/driver/tests/mdnt_mul_tests.rs @@ -1,111 +1,112 @@ -use common::llzk::basic_llzk_test; -use common::picus::basic_picus_test; -use common::synthesis_impl; -use halo2_llzk_frontend::ir::generate::IRGenParamsBuilder; -use halo2_test_circuits::mul; use halo2curves::bn256::Fr; +use haloumi::ir::r#gen::IRGenParams; +use haloumi_mdnt_test_circuits::mul; +use mdnt_common::basic_test; +use mdnt_common::synthesis_impl; -mod common; +mod mdnt_common; -basic_picus_test! { +basic_test! { mul_circuit, MulCircuitSynthesis::default(), - include_str!("expected/picus/mul_circuit.picus"), - include_str!("expected/picus/mul_circuit_opt.picus") + "mul_circuit", + "mul_circuit_opt" } -basic_llzk_test! { - mul_circuit, - MulCircuitSynthesis::default(), - include_str!("expected/llzk/mul_circuit.mlir"), - include_str!("expected/llzk/mul_circuit_opt.mlir") -} - -basic_picus_test! { +basic_test! { mul_flipped, MulFlippedCircuitSynthesis::default(), - include_str!("expected/picus/mul_flipped_constraint.picus"), - include_str!("expected/picus/mul_flipped_constraint_opt.picus") + "mul_flipped_constraint", + "mul_flipped_constraint_opt" } -basic_picus_test! { +basic_test! { mul_fixed, MulFixedConstraintCircuitSynthesis::default(), - include_str!("expected/picus/mul_with_fixed_constraint.picus"), - include_str!("expected/picus/mul_with_fixed_constraint_opt.picus") + "mul_with_fixed_constraint", + "mul_with_fixed_constraint_opt" } -basic_picus_test! { +basic_test! { recursive_groups, RecursiveMulCircuitSynthesis::default(), - include_str!("expected/picus/recursive_groups.picus"), - include_str!("expected/picus/recursive_groups_opt.picus") + "recursive_groups", + "recursive_groups_opt" } // This test makes sure that the order in which input and output variables are printed is // the same as their declaration order. -basic_picus_test! { +basic_test! { ten_plus_io, TenPlusIOCircuitSynthesis::default(), - include_str!("expected/picus/ten_plus_io.picus"), - include_str!("expected/picus/ten_plus_io_opt.picus") + "ten_plus_io", + "ten_plus_io_opt" } -basic_picus_test! { +basic_test! { grouped, GroupedMulsCircuitSynthesis::default(), - include_str!("expected/picus/grouped_muls.picus"), - include_str!("expected/picus/grouped_muls_opt.picus") + "grouped_muls", + "grouped_muls_opt" } -basic_picus_test! { +basic_test! { different_bodies, DifferentBodiesCircuitSynthesis::default(), - include_str!("expected/picus/different_bodies.picus"), - include_str!("expected/picus/different_bodies_opt.picus") + "different_bodies", + "different_bodies_opt" } -basic_picus_test! { +basic_test! { same_body, SameBodyCircuitSynthesis::default(), - include_str!("expected/picus/same_body.picus"), - include_str!("expected/picus/same_body_opt.picus") + "same_body", + "same_body_opt" } -basic_picus_test! { +basic_test! { deep_callstack, DeepCallstackCircuitSynthesis::default(), - include_str!("expected/picus/deep_callstack.picus"), - include_str!("expected/picus/deep_callstack_opt.picus") + "deep_callstack", + "deep_callstack_opt" } -basic_picus_test! { +basic_test! { mul_rewriter, MulCircuitSynthesis::default(), - include_str!("expected/picus/mul_with_rewriter.picus"), - include_str!("expected/picus/mul_with_rewriter_opt.picus"), - IRGenParamsBuilder::new().gate_callbacks(&common::GC).build() + "mul_with_rewriter", + "mul_with_rewriter_opt", + IRGenParams::new().gate_callbacks(&mdnt_common::GC) } -#[cfg(feature = "picus-backend")] mod mul_inject { use crate::ensure_validation; - use halo2_frontend_core::table::RegionIndex; - use halo2_llzk_frontend::CircuitSynthesis; - use halo2_llzk_frontend::{ - driver::Driver, expressions::ExpressionInRow, ir::ResolvedIRCircuit, + use haloumi::{ + driver::Driver, + ir::r#gen::{ + IRGenParams, circuit::resolved::ResolvedIRCircuit, expressions::ExpressionInRow, + }, + synthesis::CircuitSynthesis, }; - use halo2_midnight_integration::plonk::_Expression; - use halo2_midnight_integration::plonk::ConstraintSystem; - use halo2_proofs::plonk::Expression; + use haloumi_core::table::RegionIndex; use haloumi_ir::{CmpOp, stmt::IRStmt}; + use haloumi_midnight_integration::halo2_proofs::plonk::Expression; + use haloumi_midnight_integration::plonk::_Expression; + use haloumi_midnight_integration::plonk::ConstraintSystem; use super::*; const EXPECTED_PICUS: &str = include_str!("expected/picus/mul_inject.picus"); const EXPECTED_OPT_PICUS: &str = include_str!("expected/picus/mul_inject_opt.picus"); + const EXPECTED_LLZK: &str = include_str!("expected/llzk/mul_inject.mlir"); + const EXPECTED_OPT_LLZK: &str = include_str!("expected/llzk/mul_inject_opt.mlir"); - fn ir_to_inject<'e>() -> Vec<(RegionIndex, IRStmt>>)> { + type InjectedIR<'e> = ( + RegionIndex, + IRStmt, Fr>>, + ); + + fn ir_to_inject<'e>() -> Vec> { let mut cs = ConstraintSystem::::default(); let config = MulInjectCircuitSynthesis::configure(&mut cs); let a = config.col_a.cur(); @@ -133,9 +134,7 @@ mod mul_inject { let circuit = MulInjectCircuitSynthesis::default(); let syn = driver.synthesize(&circuit).unwrap(); - let mut unresolved = driver - .generate_ir(&syn, IRGenParamsBuilder::new().build()) - .unwrap(); + let mut unresolved = driver.generate_ir(&syn, IRGenParams::new()).unwrap(); let ir = ir_to_inject(); unresolved.inject_ir(ir, &syn).unwrap(); ensure_validation!(unresolved); @@ -144,23 +143,25 @@ mod mul_inject { resolved } + #[cfg(feature = "picus-backend")] #[test] fn picus() { - common::setup(); + mdnt_common::setup(); let mut driver = Driver::default(); let resolved = generate_ir(&mut driver); - common::picus::check_picus( + mdnt_common::picus::check_picus( &driver, &resolved, - common::picus::picus_params(), + mdnt_common::picus::picus_params(), EXPECTED_PICUS, ); } + #[cfg(feature = "picus-backend")] #[test] fn opt_picus() { - common::setup(); + mdnt_common::setup(); let mut driver = Driver::default(); let mut resolved = generate_ir(&mut driver); @@ -169,13 +170,50 @@ mod mul_inject { resolved.canonicalize(); ensure_validation!(resolved); - common::picus::check_picus( + mdnt_common::picus::check_picus( &driver, &resolved, - common::picus::opt_picus_params(), + mdnt_common::picus::opt_picus_params(), EXPECTED_OPT_PICUS, ); } + + #[cfg(feature = "llzk-backend")] + #[test] + fn llzk() { + mdnt_common::setup(); + let mut driver = Driver::default(); + let resolved = generate_ir(&mut driver); + + let ctx = llzk::context::LlzkContext::new(); + mdnt_common::llzk::check_llzk( + &driver, + &resolved, + mdnt_common::llzk::llzk_params(&ctx), + EXPECTED_LLZK, + ); + } + + #[cfg(feature = "llzk-backend")] + #[test] + fn opt_llzk() { + mdnt_common::setup(); + let mut driver = Driver::default(); + let mut resolved = generate_ir(&mut driver); + + resolved.constant_fold().unwrap(); + ensure_validation!(resolved); + resolved.canonicalize(); + ensure_validation!(resolved); + + let ctx = llzk::context::LlzkContext::new(); + mdnt_common::llzk::check_llzk( + &driver, + &resolved, + mdnt_common::llzk::opt_llzk_params(&ctx), + EXPECTED_OPT_LLZK, + ); + } } synthesis_impl!(MulCircuitSynthesis, mul::MulCircuit, [0], [1]); diff --git a/driver/tests/tests/common/mod.rs b/driver/tests/tests/common/mod.rs deleted file mode 100644 index 3936c9b..0000000 --- a/driver/tests/tests/common/mod.rs +++ /dev/null @@ -1,173 +0,0 @@ -use ff::{Field, PrimeField}; -use halo2_llzk_frontend::{ - CircuitSynthesis, - driver::Driver, - gates::{GateCallbacks, GateRewritePattern, GateScope, RewriteError}, - ir::{ResolvedIRCircuit, generate::IRGenParams}, -}; -use halo2_midnight_integration::plonk::{_Expression, ConstraintSystem}; - -pub mod llzk; -pub mod picus; - -pub fn setup() { - let _ = simplelog::TestLogger::init(log::LevelFilter::Debug, simplelog::Config::default()); -} - -#[macro_export] -macro_rules! ensure_validation { - ($x:expr) => {{ - let (status, errs) = $x.validate(); - - if status.is_err() { - for err in errs { - log::error!("{err}"); - } - panic!("Test failed due to validation errors"); - } - }}; -} - -/// We run the synthesis separately to test that the lifetimes of the values -/// can be untied to the CircuitSynthesis struct. But also if we want to add LLZK tests -/// this makes sure to test the retargeability of the driver. -pub fn synthesize_and_generate_ir( - driver: &mut Driver, - circuit: C, - params: IRGenParams>, -) -> ResolvedIRCircuit -where - F: PrimeField + std::cmp::Ord, - C: CircuitSynthesis, - C: CircuitSynthesis>, -{ - let syn = driver.synthesize(&circuit).unwrap(); - let unresolved = driver.generate_ir(&syn, params).unwrap(); - ensure_validation!(unresolved); - let resolved = unresolved.resolve().unwrap(); - ensure_validation!(resolved); - resolved -} - -fn common_lowering( - circuit: C, - driver: &mut Driver, - ir_params: IRGenParams>, - canonicalize: bool, -) -> ResolvedIRCircuit -where - F: PrimeField + std::cmp::Ord, - C: CircuitSynthesis>, -{ - let mut resolved = synthesize_and_generate_ir(driver, circuit, ir_params); - if canonicalize { - resolved.constant_fold().unwrap(); - ensure_validation!(resolved); - resolved.canonicalize(); - ensure_validation!(resolved); - } - resolved -} - -fn clean_string(s: &str) -> String { - let mut r = String::with_capacity(s.len()); - for line in s.lines() { - let line = line.trim(); - if line.starts_with(";") || line.is_empty() { - continue; - } - let line = match line.find(';') { - Some(idx) => &line[..idx], - None => line, - } - .trim(); - - r.push_str(line); - r.push('\n'); - } - r -} - -#[allow(dead_code)] -struct DummyPattern; - -impl GateRewritePattern> for DummyPattern { - fn match_gate<'a>( - &self, - _gate: GateScope<'a, '_, F, _Expression>, - ) -> Result<(), RewriteError> - where - F: Field, - { - Err(RewriteError::NoMatch) - } -} - -#[allow(dead_code)] -pub struct GC; - -impl GateCallbacks> for GC { - fn patterns(&self) -> Vec>>> - where - F: Field, - { - vec![Box::new(DummyPattern)] - } -} - -macro_rules! synthesis_impl { - ($name:ident, $circuit:ty, $inputs:expr, $outputs:expr) => { - #[derive(Default)] - struct $name($circuit); - - impl halo2_llzk_frontend::CircuitSynthesis for $name { - type Circuit = $circuit; - type Config = - <$circuit as halo2_proofs::plonk::Circuit>::Config; - - type CS = halo2_midnight_integration::plonk::ConstraintSystem; - - type Error = halo2_proofs::plonk::Error; - - fn circuit(&self) -> &Self::Circuit { - &self.0 - } - fn configure(cs: &mut Self::CS) -> Self::Config { - <$circuit as halo2_proofs::plonk::Circuit>::configure( - cs.inner_mut(), - ) - } - - fn advice_io(_: &Self::Config) -> anyhow::Result { - Ok(halo2_llzk_frontend::CircuitIO::empty()) - } - fn instance_io( - config: &Self::Config, - ) -> anyhow::Result { - halo2_llzk_frontend::CircuitIO::new::< - halo2_midnight_integration::plonk::_Column< - halo2_midnight_integration::plonk::_Instance, - >, - >( - &[(config.instance.into(), &$inputs)], - &[(config.instance.into(), &$outputs)], - ) - } - fn synthesize( - circuit: &Self::Circuit, - config: Self::Config, - synthesizer: &mut halo2_llzk_frontend::Synthesizer, - cs: &Self::CS, - ) -> Result<(), Self::Error> { - halo2_midnight_integration::synthesizer::SynthesizerAssignment::synthesize( - circuit, - config, - synthesizer, - cs, - ) - } - } - }; -} - -pub(crate) use synthesis_impl; diff --git a/driver/tests/tests/expected/llzk/mul_circuit.mlir b/driver/tests/tests/expected/llzk/mul_circuit.mlir deleted file mode 100644 index 067c6c6..0000000 --- a/driver/tests/tests/expected/llzk/mul_circuit.mlir +++ /dev/null @@ -1,55 +0,0 @@ -module attributes {veridise.lang = "llzk"} { - struct.def @Signal<[]> { - struct.field @reg : !felt.type {llzk.pub} - function.def @compute(%arg0: !felt.type) -> !struct.type<@Signal<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Signal<[]>> - struct.writef %self[@reg] = %arg0 : <@Signal<[]>>, !felt.type - function.return %self : !struct.type<@Signal<[]>> - } - function.def @constrain(%arg0: !struct.type<@Signal<[]>>, %arg1: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %arg1 : !felt.type, !felt.type - function.return - } - } - struct.def @Main<[]> { - struct.field @out_0 : !felt.type {llzk.pub} - function.def @compute(%arg0: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Main<[]>> - function.return %self : !struct.type<@Main<[]>> - } - function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %felt_1 = felt.const 1 - %felt_minus_1 = felt.const 21888242871839275222246405745257275088548364400416034343698204186575808495616 - %0 = struct.readf %arg0[@adv_0_0] : <@Main<[]>>, !felt.type - %1 = felt.mul %felt_minus_1, %0 : !felt.type, !felt.type - %2 = struct.readf %arg0[@adv_1_0] : <@Main<[]>>, !felt.type - %3 = felt.neg %2 : !felt.type - %4 = felt.add %1, %3 : !felt.type, !felt.type - %5 = felt.mul %felt_1, %4 : !felt.type, !felt.type - %felt_0 = felt.const 0 - constrain.eq %5, %felt_0 : !felt.type, !felt.type - %felt_1_0 = felt.const 1 - %6 = struct.readf %arg0[@adv_0_0] : <@Main<[]>>, !felt.type - %7 = struct.readf %arg0[@adv_1_0] : <@Main<[]>>, !felt.type - %8 = felt.mul %6, %7 : !felt.type, !felt.type - %9 = struct.readf %arg0[@adv_2_0] : <@Main<[]>>, !felt.type - %10 = felt.neg %9 : !felt.type - %11 = felt.add %8, %10 : !felt.type, !felt.type - %12 = felt.mul %felt_1_0, %11 : !felt.type, !felt.type - %felt_0_1 = felt.const 0 - constrain.eq %12, %felt_0_1 : !felt.type, !felt.type - %13 = struct.readf %arg0[@adv_0_0] : <@Main<[]>>, !felt.type - %14 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %13, %14 : !felt.type, !felt.type - %15 = struct.readf %arg0[@adv_2_0] : <@Main<[]>>, !felt.type - %16 = struct.readf %arg0[@out_0] : <@Main<[]>>, !felt.type - constrain.eq %15, %16 : !felt.type, !felt.type - function.return - } - struct.field @adv_0_0 : !felt.type - struct.field @adv_1_0 : !felt.type - struct.field @adv_2_0 : !felt.type - } -} - diff --git a/driver/tests/tests/expected/llzk/mul_circuit_opt.mlir b/driver/tests/tests/expected/llzk/mul_circuit_opt.mlir deleted file mode 100644 index ea08483..0000000 --- a/driver/tests/tests/expected/llzk/mul_circuit_opt.mlir +++ /dev/null @@ -1,40 +0,0 @@ -module attributes {veridise.lang = "llzk"} { - struct.def @Signal<[]> { - struct.field @reg : !felt.type {llzk.pub} - function.def @compute(%arg0: !felt.type) -> !struct.type<@Signal<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Signal<[]>> - struct.writef %self[@reg] = %arg0 : <@Signal<[]>>, !felt.type - function.return %self : !struct.type<@Signal<[]>> - } - function.def @constrain(%arg0: !struct.type<@Signal<[]>>, %arg1: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %arg1 : !felt.type, !felt.type - function.return - } - } - struct.def @Main<[]> { - struct.field @out_0 : !felt.type {llzk.pub} - function.def @compute(%arg0: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Main<[]>> - function.return %self : !struct.type<@Main<[]>> - } - function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@adv_0_0] : <@Main<[]>>, !felt.type - %1 = felt.neg %0 : !felt.type - %2 = struct.readf %arg0[@adv_1_0] : <@Main<[]>>, !felt.type - constrain.eq %1, %2 : !felt.type, !felt.type - %5 = felt.mul %0, %2 : !felt.type, !felt.type - %6 = struct.readf %arg0[@adv_2_0] : <@Main<[]>>, !felt.type - constrain.eq %5, %6 : !felt.type, !felt.type - %8 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %8 : !felt.type, !felt.type - %10 = struct.readf %arg0[@out_0] : <@Main<[]>>, !felt.type - constrain.eq %6, %10 : !felt.type, !felt.type - function.return - } - struct.field @adv_0_0 : !felt.type - struct.field @adv_1_0 : !felt.type - struct.field @adv_2_0 : !felt.type - } -} - diff --git a/driver/tests/tests/expected/picus/deep_callstack.picus b/driver/tests/tests/expected/picus/deep_callstack.picus deleted file mode 100644 index e049111..0000000 --- a/driver/tests/tests/expected/picus/deep_callstack.picus +++ /dev/null @@ -1,44 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module test_group) -(input in_0) -(output out_0) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_1) (- adv_1_1))) 0)) -(assert (= (* 1 (+ (* adv_0_1 adv_1_1) (- out_0))) 0)) -(assert (= in_0 adv_0_1)) -(end-module) -(begin-module test_group1) -(input in_0) -(output out_0) -(assert (= (* 1 (+ (* adv_0_3 adv_1_3) (- out_0))) 0)) -(assert (= in_0 adv_0_3)) -(end-module) -(begin-module inner_group) -(input in_0) -(output out_0) -(assert (= (* 1 (+ (* adv_0_4 adv_1_4) (- out_0))) 0)) -(assert (= in_0 adv_0_4)) -(end-module) -(begin-module outer_group) -(input in_0) -(output out_0) -(call [cout_0_0] inner_group [in_0]) -(assert (= adv_2_4 cout_0_0)) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_5) (- adv_1_5))) 0)) -(assert (= (* 1 (+ (* adv_0_5 adv_1_5) (- out_0))) 0)) -(assert (= adv_2_4 adv_0_5)) -(end-module) -(begin-module Main) -(input in_0) -(output out_0) -(call [cout_0_0] test_group [adv_0_0]) -(assert (= adv_2_1 cout_0_0)) -(call [cout_1_0] test_group [adv_2_1]) -(assert (= adv_2_2 cout_1_0)) -(call [cout_2_0] test_group1 [adv_2_2]) -(assert (= adv_2_3 cout_2_0)) -(call [cout_3_0] outer_group [adv_2_3]) -(assert (= adv_2_5 cout_3_0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_2_5 adv_2_6)) -(assert (= adv_2_6 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/deep_callstack_opt.picus b/driver/tests/tests/expected/picus/deep_callstack_opt.picus deleted file mode 100644 index ed2f912..0000000 --- a/driver/tests/tests/expected/picus/deep_callstack_opt.picus +++ /dev/null @@ -1,32 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module test_group) -(input in_0) -(output out_0) -(assert (= (- in_0) adv_1_1)) -(assert (= (* in_0 adv_1_1) out_0)) -(end-module) -(begin-module test_group1) -(input in_0) -(output out_0) -(assert (= (* in_0 adv_1_3) out_0)) -(end-module) -(begin-module inner_group) -(input in_0) -(output out_0) -(assert (= (* in_0 adv_1_4) out_0)) -(end-module) -(begin-module outer_group) -(input in_0) -(output out_0) -(call [adv_2_4] inner_group [in_0]) -(assert (= (- adv_2_4) adv_1_5)) -(assert (= (* adv_2_4 adv_1_5) out_0)) -(end-module) -(begin-module Main) -(input in_0) -(output out_0) -(call [adv_2_1] test_group [in_0]) -(call [adv_2_2] test_group [adv_2_1]) -(call [adv_2_3] test_group1 [adv_2_2]) -(call [out_0] outer_group [adv_2_3]) -(end-module) diff --git a/driver/tests/tests/expected/picus/different_bodies.picus b/driver/tests/tests/expected/picus/different_bodies.picus deleted file mode 100644 index f2527c6..0000000 --- a/driver/tests/tests/expected/picus/different_bodies.picus +++ /dev/null @@ -1,27 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module test_group) -(input in_0) -(output out_0) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_1) (- adv_1_1))) 0)) -(assert (= (* 1 (+ (* adv_0_1 adv_1_1) (- out_0))) 0)) -(assert (= in_0 adv_0_1)) -(end-module) -(begin-module test_group1) -(input in_0) -(output out_0) -(assert (= (* 1 (+ (* adv_0_3 adv_1_3) (- out_0))) 0)) -(assert (= in_0 adv_0_3)) -(end-module) -(begin-module Main) -(input in_0) -(output out_0) -(call [cout_0_0] test_group [adv_0_0]) -(assert (= adv_2_1 cout_0_0)) -(call [cout_1_0] test_group [adv_2_1]) -(assert (= adv_2_2 cout_1_0)) -(call [cout_2_0] test_group1 [adv_2_2]) -(assert (= adv_2_3 cout_2_0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_2_3 adv_2_4)) -(assert (= adv_2_4 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/different_bodies_opt.picus b/driver/tests/tests/expected/picus/different_bodies_opt.picus deleted file mode 100644 index 0ebd413..0000000 --- a/driver/tests/tests/expected/picus/different_bodies_opt.picus +++ /dev/null @@ -1,19 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module test_group) -(input in_0) -(output out_0) -(assert (= (- in_0) adv_1_1)) -(assert (= (* in_0 adv_1_1) out_0)) -(end-module) -(begin-module test_group1) -(input in_0) -(output out_0) -(assert (= (* in_0 adv_1_3) out_0)) -(end-module) -(begin-module Main) -(input in_0) -(output out_0) -(call [adv_2_1] test_group [in_0]) -(call [adv_2_2] test_group [adv_2_1]) -(call [out_0] test_group1 [adv_2_2]) -(end-module) diff --git a/driver/tests/tests/expected/picus/fibonacci.picus b/driver/tests/tests/expected/picus/fibonacci.picus deleted file mode 100644 index c19e34f..0000000 --- a/driver/tests/tests/expected/picus/fibonacci.picus +++ /dev/null @@ -1,31 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(input in_1) -(output out_0) -(assert (= (* 1 (+ (+ adv_0_0 adv_1_0) (- adv_2_0))) 0)) -(assert (= (* 1 (+ (+ adv_0_1 adv_1_1) (- adv_2_1))) 0)) -(assert (= (* 1 (+ (+ adv_0_2 adv_1_2) (- adv_2_2))) 0)) -(assert (= (* 1 (+ (+ adv_0_3 adv_1_3) (- adv_2_3))) 0)) -(assert (= (* 1 (+ (+ adv_0_4 adv_1_4) (- adv_2_4))) 0)) -(assert (= (* 1 (+ (+ adv_0_5 adv_1_5) (- adv_2_5))) 0)) -(assert (= (* 1 (+ (+ adv_0_6 adv_1_6) (- adv_2_6))) 0)) -(assert (= (* 1 (+ (+ adv_0_7 adv_1_7) (- adv_2_7))) 0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_0_1 adv_1_0)) -(assert (= adv_0_2 adv_2_0)) -(assert (= adv_0_3 adv_2_1)) -(assert (= adv_0_4 adv_2_2)) -(assert (= adv_0_5 adv_2_3)) -(assert (= adv_0_6 adv_2_4)) -(assert (= adv_0_7 adv_2_5)) -(assert (= adv_1_0 in_1)) -(assert (= adv_1_1 adv_2_0)) -(assert (= adv_1_2 adv_2_1)) -(assert (= adv_1_3 adv_2_2)) -(assert (= adv_1_4 adv_2_3)) -(assert (= adv_1_5 adv_2_4)) -(assert (= adv_1_6 adv_2_5)) -(assert (= adv_1_7 adv_2_6)) -(assert (= adv_2_7 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/fibonacci_grouped.picus b/driver/tests/tests/expected/picus/fibonacci_grouped.picus deleted file mode 100644 index 329b8e7..0000000 --- a/driver/tests/tests/expected/picus/fibonacci_grouped.picus +++ /dev/null @@ -1,43 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module fib) -(input in_0) -(input in_1) -(output out_0) -(output out_1) -(assert (= (* 1 (+ (+ adv_0_1 adv_1_1) (- out_1))) 0)) -(assert (= adv_0_1 in_0)) -(assert (= adv_1_1 out_0)) -(assert (= in_1 out_0)) -(end-module) -(begin-module Main) -(input in_0) -(input in_1) -(output out_0) -(output out_1) -(call [cout_0_0 cout_0_1] fib [adv_0_0 adv_1_0]) -(assert (= adv_1_0 cout_0_0)) -(assert (= adv_2_1 cout_0_1)) -(call [cout_1_0 cout_1_1] fib [adv_1_0 adv_2_1]) -(assert (= adv_2_1 cout_1_0)) -(assert (= adv_2_2 cout_1_1)) -(call [cout_2_0 cout_2_1] fib [adv_2_1 adv_2_2]) -(assert (= adv_2_2 cout_2_0)) -(assert (= adv_2_3 cout_2_1)) -(call [cout_3_0 cout_3_1] fib [adv_2_2 adv_2_3]) -(assert (= adv_2_3 cout_3_0)) -(assert (= adv_2_4 cout_3_1)) -(call [cout_4_0 cout_4_1] fib [adv_2_3 adv_2_4]) -(assert (= adv_2_4 cout_4_0)) -(assert (= adv_2_5 cout_4_1)) -(call [cout_5_0 cout_5_1] fib [adv_2_4 adv_2_5]) -(assert (= adv_2_5 cout_5_0)) -(assert (= adv_2_6 cout_5_1)) -(call [cout_6_0 cout_6_1] fib [adv_2_5 adv_2_6]) -(assert (= adv_2_6 cout_6_0)) -(assert (= adv_2_7 cout_6_1)) -(assert (= (* 1 (+ (+ adv_0_0 adv_1_0) (- adv_2_0))) 0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_1_0 in_1)) -(assert (= adv_2_6 out_0)) -(assert (= adv_2_7 out_1)) -(end-module) diff --git a/driver/tests/tests/expected/picus/fibonacci_grouped_opt.picus b/driver/tests/tests/expected/picus/fibonacci_grouped_opt.picus deleted file mode 100644 index 3cd4450..0000000 --- a/driver/tests/tests/expected/picus/fibonacci_grouped_opt.picus +++ /dev/null @@ -1,24 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module fib) -(input in_0) -(input in_1) -(output out_0) -(output out_1) -(assert (= (+ in_0 in_1) out_1)) -(assert (= in_1 out_0)) -(assert (= in_1 out_0)) -(end-module) -(begin-module Main) -(input in_0) -(input in_1) -(output out_0) -(output out_1) -(call [in_1 adv_2_1] fib [in_0 in_1]) -(call [adv_2_1 adv_2_2] fib [in_1 adv_2_1]) -(call [adv_2_2 adv_2_3] fib [adv_2_1 adv_2_2]) -(call [adv_2_3 adv_2_4] fib [adv_2_2 adv_2_3]) -(call [adv_2_4 adv_2_5] fib [adv_2_3 adv_2_4]) -(call [adv_2_5 out_0] fib [adv_2_4 adv_2_5]) -(call [out_0 out_1] fib [adv_2_5 out_0]) -(assert (= (+ in_0 in_1) adv_2_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/fibonacci_opt.picus b/driver/tests/tests/expected/picus/fibonacci_opt.picus deleted file mode 100644 index 51922da..0000000 --- a/driver/tests/tests/expected/picus/fibonacci_opt.picus +++ /dev/null @@ -1,14 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(input in_1) -(output out_0) -(assert (= (+ in_0 in_1) adv_0_2)) -(assert (= (+ in_1 adv_0_2) adv_0_3)) -(assert (= (+ adv_0_2 adv_0_3) adv_0_4)) -(assert (= (+ adv_0_3 adv_0_4) adv_0_5)) -(assert (= (+ adv_0_4 adv_0_5) adv_0_6)) -(assert (= (+ adv_0_5 adv_0_6) adv_0_7)) -(assert (= (+ adv_0_6 adv_0_7) adv_1_7)) -(assert (= (+ adv_0_7 adv_1_7) out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/grouped_muls.picus b/driver/tests/tests/expected/picus/grouped_muls.picus deleted file mode 100644 index 8bdd47a..0000000 --- a/driver/tests/tests/expected/picus/grouped_muls.picus +++ /dev/null @@ -1,13 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module test_group) -(output out_0) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_0) (- adv_1_0))) 0)) -(assert (= (* 1 (+ (* adv_0_0 adv_1_0) (- out_0))) 0)) -(end-module) -(begin-module Main) -(input in_0) -(output out_0) -(call [cout_0_0] test_group []) -(assert (= adv_2_0 cout_0_0)) -(assert (= adv_2_0 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/grouped_muls_opt.picus b/driver/tests/tests/expected/picus/grouped_muls_opt.picus deleted file mode 100644 index d338849..0000000 --- a/driver/tests/tests/expected/picus/grouped_muls_opt.picus +++ /dev/null @@ -1,11 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module test_group) -(output out_0) -(assert (= (- adv_0_0) adv_1_0)) -(assert (= (* adv_0_0 adv_1_0) out_0)) -(end-module) -(begin-module Main) -(input in_0) -(output out_0) -(call [out_0] test_group []) -(end-module) diff --git a/driver/tests/tests/expected/picus/lookup.picus b/driver/tests/tests/expected/picus/lookup.picus deleted file mode 100644 index 7eec7c2..0000000 --- a/driver/tests/tests/expected/picus/lookup.picus +++ /dev/null @@ -1,9 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= (* 1 (+ (* adv_1_0 adv_0_0) (- adv_2_0))) 0)) -(assert (= (* 1 (+ (* adv_0_0 adv_2_0) (- adv_3_0))) 0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_3_0 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/lookup_2x3.picus b/driver/tests/tests/expected/picus/lookup_2x3.picus deleted file mode 100644 index 7548963..0000000 --- a/driver/tests/tests/expected/picus/lookup_2x3.picus +++ /dev/null @@ -1,7 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= adv_0_0 in_0)) -(assert (= adv_3_0 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/lookup_2x3_opt.picus b/driver/tests/tests/expected/picus/lookup_2x3_opt.picus deleted file mode 100644 index 80823b2..0000000 --- a/driver/tests/tests/expected/picus/lookup_2x3_opt.picus +++ /dev/null @@ -1,5 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(end-module) diff --git a/driver/tests/tests/expected/picus/lookup_opt.picus b/driver/tests/tests/expected/picus/lookup_opt.picus deleted file mode 100644 index eda7c85..0000000 --- a/driver/tests/tests/expected/picus/lookup_opt.picus +++ /dev/null @@ -1,7 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= (* adv_1_0 in_0) adv_2_0)) -(assert (= (* in_0 adv_2_0) out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/mul_circuit.picus b/driver/tests/tests/expected/picus/mul_circuit.picus deleted file mode 100644 index 67d3466..0000000 --- a/driver/tests/tests/expected/picus/mul_circuit.picus +++ /dev/null @@ -1,9 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_0) (- adv_1_0))) 0)) -(assert (= (* 1 (+ (* adv_0_0 adv_1_0) (- adv_2_0))) 0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_2_0 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/mul_circuit_opt.picus b/driver/tests/tests/expected/picus/mul_circuit_opt.picus deleted file mode 100644 index a2f1bb6..0000000 --- a/driver/tests/tests/expected/picus/mul_circuit_opt.picus +++ /dev/null @@ -1,7 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= (- in_0) adv_1_0)) -(assert (= (* in_0 adv_1_0) out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/mul_flipped_constraint.picus b/driver/tests/tests/expected/picus/mul_flipped_constraint.picus deleted file mode 100644 index 59b7405..0000000 --- a/driver/tests/tests/expected/picus/mul_flipped_constraint.picus +++ /dev/null @@ -1,9 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_0) (- adv_1_0))) 0)) -(assert (= (* 1 (+ (- adv_2_0) (* adv_0_0 adv_1_0))) 0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_2_0 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/mul_flipped_constraint_opt.picus b/driver/tests/tests/expected/picus/mul_flipped_constraint_opt.picus deleted file mode 100644 index 5e23206..0000000 --- a/driver/tests/tests/expected/picus/mul_flipped_constraint_opt.picus +++ /dev/null @@ -1,7 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= (- in_0) adv_1_0)) -(assert (= out_0 (* in_0 adv_1_0))) -(end-module) diff --git a/driver/tests/tests/expected/picus/mul_inject.picus b/driver/tests/tests/expected/picus/mul_inject.picus deleted file mode 100644 index ef176b0..0000000 --- a/driver/tests/tests/expected/picus/mul_inject.picus +++ /dev/null @@ -1,25 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(output out_1) -(output out_2) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_0) (- adv_0_1))) 0)) -(assert (= (* 1 (+ (* adv_0_0 adv_0_1) (- adv_1_0))) 0)) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_2) (- adv_0_3))) 0)) -(assert (= (* 1 (+ (* adv_0_2 adv_0_3) (- adv_1_2))) 0)) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_4) (- adv_0_5))) 0)) -(assert (= (* 1 (+ (* adv_0_4 adv_0_5) (- adv_1_4))) 0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_0_2 in_0)) -(assert (= adv_0_4 in_0)) -(assert (= adv_1_0 out_0)) -(assert (= adv_1_2 out_1)) -(assert (= adv_1_4 out_2)) -(assert (< adv_0_0 1000)) -(assert (>= adv_0_1 1000)) -(assert (< adv_0_2 1000)) -(assert (>= adv_0_3 1000)) -(assert (< adv_0_4 1000)) -(assert (>= adv_0_5 1000)) -(end-module) diff --git a/driver/tests/tests/expected/picus/mul_inject_opt.picus b/driver/tests/tests/expected/picus/mul_inject_opt.picus deleted file mode 100644 index b0fe967..0000000 --- a/driver/tests/tests/expected/picus/mul_inject_opt.picus +++ /dev/null @@ -1,19 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(output out_1) -(output out_2) -(assert (= (- in_0) adv_0_1)) -(assert (= (* in_0 adv_0_1) out_0)) -(assert (= (- in_0) adv_0_3)) -(assert (= (* in_0 adv_0_3) out_1)) -(assert (= (- in_0) adv_0_5)) -(assert (= (* in_0 adv_0_5) out_2)) -(assert (< in_0 1000)) -(assert (>= adv_0_1 1000)) -(assert (< in_0 1000)) -(assert (>= adv_0_3 1000)) -(assert (< in_0 1000)) -(assert (>= adv_0_5 1000)) -(end-module) diff --git a/driver/tests/tests/expected/picus/mul_test.picus b/driver/tests/tests/expected/picus/mul_test.picus deleted file mode 100644 index 8981399..0000000 --- a/driver/tests/tests/expected/picus/mul_test.picus +++ /dev/null @@ -1,10 +0,0 @@ -; vim: set filetype=scheme : -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_0) (- adv_1_0))) 0)) -(assert (= (* 1 (+ (* adv_0_0 adv_1_0) (- adv_2_0))) 0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_2_0 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/mul_test_opt.picus b/driver/tests/tests/expected/picus/mul_test_opt.picus deleted file mode 100644 index 207692a..0000000 --- a/driver/tests/tests/expected/picus/mul_test_opt.picus +++ /dev/null @@ -1,8 +0,0 @@ -; vim: set filetype=scheme : -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= (- in_0) adv_1_0)) -(assert (= (* in_0 adv_1_0) out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/mul_with_fixed_constraint_opt.picus b/driver/tests/tests/expected/picus/mul_with_fixed_constraint_opt.picus deleted file mode 100644 index a2f1bb6..0000000 --- a/driver/tests/tests/expected/picus/mul_with_fixed_constraint_opt.picus +++ /dev/null @@ -1,7 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= (- in_0) adv_1_0)) -(assert (= (* in_0 adv_1_0) out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/mul_with_rewriter.picus b/driver/tests/tests/expected/picus/mul_with_rewriter.picus deleted file mode 100644 index 67d3466..0000000 --- a/driver/tests/tests/expected/picus/mul_with_rewriter.picus +++ /dev/null @@ -1,9 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_0) (- adv_1_0))) 0)) -(assert (= (* 1 (+ (* adv_0_0 adv_1_0) (- adv_2_0))) 0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_2_0 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/mul_with_rewriter_opt.picus b/driver/tests/tests/expected/picus/mul_with_rewriter_opt.picus deleted file mode 100644 index a2f1bb6..0000000 --- a/driver/tests/tests/expected/picus/mul_with_rewriter_opt.picus +++ /dev/null @@ -1,7 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(output out_0) -(assert (= (- in_0) adv_1_0)) -(assert (= (* in_0 adv_1_0) out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/recursive_groups.picus b/driver/tests/tests/expected/picus/recursive_groups.picus deleted file mode 100644 index 3ae3b61..0000000 --- a/driver/tests/tests/expected/picus/recursive_groups.picus +++ /dev/null @@ -1,47 +0,0 @@ - -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module mul_many) -(input in_0) -(input in_1) -(output out_0) -(assert (= (* 1 (+ (* adv_0_4 adv_1_4) (- out_0))) 0)) -(assert (= in_0 adv_0_4)) -(assert (= in_1 adv_1_4)) -(end-module) -(begin-module mul_many1) -(input in_0) -(input in_1) -(input in_2) -(output out_0) -(call [cout_0_0] mul_many [in_1 in_2]) -(assert (= adv_2_4 cout_0_0)) -(assert (= (* 1 (+ (* adv_0_5 adv_1_5) (- out_0))) 0)) -(assert (= in_0 adv_0_5)) -(assert (= adv_2_4 adv_1_5)) -(end-module) -(begin-module mul_many2) -(input in_0) -(input in_1) -(input in_2) -(input in_3) -(output out_0) -(call [cout_0_0] mul_many1 [in_1 in_2 in_3]) -(assert (= adv_2_5 cout_0_0)) -(assert (= (* 1 (+ (* adv_0_6 adv_1_6) (- out_0))) 0)) -(assert (= in_0 adv_0_6)) -(assert (= adv_2_5 adv_1_6)) -(end-module) -(begin-module Main) -(input in_0) -(input in_1) -(input in_2) -(input in_3) -(output out_0) -(call [cout_0_0] mul_many2 [adv_0_0 adv_0_1 adv_0_2 adv_0_3]) -(assert (= adv_2_6 cout_0_0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_0_1 in_1)) -(assert (= adv_0_2 in_2)) -(assert (= adv_0_3 in_3)) -(assert (= adv_2_6 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/recursive_groups_opt.picus b/driver/tests/tests/expected/picus/recursive_groups_opt.picus deleted file mode 100644 index 426ba46..0000000 --- a/driver/tests/tests/expected/picus/recursive_groups_opt.picus +++ /dev/null @@ -1,32 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module mul_many) -(input in_0) -(input in_1) -(output out_0) -(assert (= (* in_0 in_1) out_0)) -(end-module) -(begin-module mul_many1) -(input in_0) -(input in_1) -(input in_2) -(output out_0) -(call [adv_2_4] mul_many [in_1 in_2]) -(assert (= (* in_0 adv_2_4) out_0)) -(end-module) -(begin-module mul_many2) -(input in_0) -(input in_1) -(input in_2) -(input in_3) -(output out_0) -(call [adv_2_5] mul_many1 [in_1 in_2 in_3]) -(assert (= (* in_0 adv_2_5) out_0)) -(end-module) -(begin-module Main) -(input in_0) -(input in_1) -(input in_2) -(input in_3) -(output out_0) -(call [out_0] mul_many2 [in_0 in_1 in_2 in_3]) -(end-module) diff --git a/driver/tests/tests/expected/picus/same_body.picus b/driver/tests/tests/expected/picus/same_body.picus deleted file mode 100644 index 4c72792..0000000 --- a/driver/tests/tests/expected/picus/same_body.picus +++ /dev/null @@ -1,19 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module test_group) -(input in_0) -(output out_0) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_1) (- adv_1_1))) 0)) -(assert (= (* 1 (+ (* adv_0_1 adv_1_1) (- out_0))) 0)) -(assert (= in_0 adv_0_1)) -(end-module) -(begin-module Main) -(input in_0) -(output out_0) -(call [cout_0_0] test_group [adv_0_0]) -(assert (= adv_2_1 cout_0_0)) -(call [cout_1_0] test_group [adv_2_1]) -(assert (= adv_2_2 cout_1_0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_2_2 adv_2_3)) -(assert (= adv_2_3 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/same_body_opt.picus b/driver/tests/tests/expected/picus/same_body_opt.picus deleted file mode 100644 index 6bdcc73..0000000 --- a/driver/tests/tests/expected/picus/same_body_opt.picus +++ /dev/null @@ -1,13 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module test_group) -(input in_0) -(output out_0) -(assert (= (- in_0) adv_1_1)) -(assert (= (* in_0 adv_1_1) out_0)) -(end-module) -(begin-module Main) -(input in_0) -(output out_0) -(call [adv_2_1] test_group [in_0]) -(call [out_0] test_group [adv_2_1]) -(end-module) diff --git a/driver/tests/tests/expected/picus/ten_plus_io.picus b/driver/tests/tests/expected/picus/ten_plus_io.picus deleted file mode 100644 index 1b1b5ea..0000000 --- a/driver/tests/tests/expected/picus/ten_plus_io.picus +++ /dev/null @@ -1,29 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(input in_1) -(input in_2) -(input in_3) -(input in_4) -(input in_5) -(input in_6) -(input in_7) -(input in_8) -(input in_9) -(input in_10) -(output out_0) -(output out_1) -(output out_2) -(output out_3) -(output out_4) -(output out_5) -(output out_6) -(output out_7) -(output out_8) -(output out_9) -(output out_10) -(assert (= (* 1 (+ (* 21888242871839275222246405745257275088548364400416034343698204186575808495616 adv_0_0) (- adv_1_0))) 0)) -(assert (= (* 1 (+ (* adv_0_0 adv_1_0) (- adv_2_0))) 0)) -(assert (= adv_0_0 in_0)) -(assert (= adv_2_0 out_0)) -(end-module) diff --git a/driver/tests/tests/expected/picus/ten_plus_io_opt.picus b/driver/tests/tests/expected/picus/ten_plus_io_opt.picus deleted file mode 100644 index 3da9d5e..0000000 --- a/driver/tests/tests/expected/picus/ten_plus_io_opt.picus +++ /dev/null @@ -1,27 +0,0 @@ -(prime-number 21888242871839275222246405745257275088548364400416034343698204186575808495617) -(begin-module Main) -(input in_0) -(input in_1) -(input in_2) -(input in_3) -(input in_4) -(input in_5) -(input in_6) -(input in_7) -(input in_8) -(input in_9) -(input in_10) -(output out_0) -(output out_1) -(output out_2) -(output out_3) -(output out_4) -(output out_5) -(output out_6) -(output out_7) -(output out_8) -(output out_9) -(output out_10) -(assert (= (- in_0) adv_1_0)) -(assert (= (* in_0 adv_1_0) out_0)) -(end-module) diff --git a/driver/tests/tests/common/llzk.rs b/driver/tests/zcash_common/llzk.rs similarity index 63% rename from driver/tests/tests/common/llzk.rs rename to driver/tests/zcash_common/llzk.rs index 5d8881a..2fd863b 100644 --- a/driver/tests/tests/common/llzk.rs +++ b/driver/tests/zcash_common/llzk.rs @@ -1,34 +1,39 @@ #[cfg(feature = "llzk-backend")] mod inner { use ff::PrimeField; - use halo2_llzk_frontend::{ - CircuitSynthesis, LlzkParams, LlzkParamsBuilder, - driver::Driver, - ir::{ResolvedIRCircuit, generate::IRGenParams}, - }; - use halo2_midnight_integration::plonk::{_Expression, ConstraintSystem}; + use haloumi::{ir::r#gen::IRGenParams, ir::r#gen::circuit::resolved::ResolvedIRCircuit}; + use haloumi_llzk::LlzkParams; use llzk::prelude::{LlzkContext, OperationLike as _}; + use zcash_halo2_proofs::{ + dev::haloumi::{Haloumi, SynthesizableCircuit}, + plonk::Expression, + }; - use crate::common::common_lowering; + use crate::zcash_common::common_lowering; #[allow(dead_code)] pub fn llzk_params(ctx: &LlzkContext) -> LlzkParams<'_> { - LlzkParamsBuilder::new(ctx).no_optimize().build() + LlzkParams::new(ctx) + .no_optimize() + // The field is named `halo2curves::bn256` but LLZK uses the bn254 name instead. + .with_builtin_field("bn254") } #[allow(dead_code)] pub fn opt_llzk_params(ctx: &LlzkContext) -> LlzkParams<'_> { - LlzkParamsBuilder::new(ctx).build() + LlzkParams::new(ctx) + // The field is named `halo2curves::bn256` but LLZK uses the bn254 name instead. + .with_builtin_field("bn254") } #[allow(dead_code)] pub fn check_llzk( - driver: &Driver, + driver: &Haloumi, circuit: &ResolvedIRCircuit, params: LlzkParams, expected_llzk: impl AsRef, ) { - let output = driver.llzk(circuit, params).unwrap(); + let output = driver.generate_llzk(circuit, params).unwrap(); assert!(output.module().as_operation().verify()); mlir_testutils::assert_module_eq(output.module(), expected_llzk.as_ref()); } @@ -37,14 +42,14 @@ mod inner { pub fn llzk_test( circuit: C, params: LlzkParams, - ir_params: IRGenParams>, + ir_params: IRGenParams>, expected_llzk: impl AsRef, canonicalize: bool, ) where F: PrimeField + std::cmp::Ord, - C: CircuitSynthesis>, + C: SynthesizableCircuit, { - let mut driver = Driver::default(); + let mut driver = Haloumi::default(); let resolved = common_lowering(circuit, &mut driver, ir_params, canonicalize); log::info!("Completed IR lowering!"); log::logger().flush(); @@ -63,15 +68,15 @@ macro_rules! basic_llzk_test { ($name:ident, $circuit:expr, $expected:expr, $expected_opt:expr, $ir_params:expr $(,)?) => { paste::paste! { #[cfg(feature = "llzk-backend")] - mod [< $name _llzk >] { + mod [] { use super::*; #[test] fn no_opt() { - common::setup(); + zcash_common::setup(); let ctx = llzk::context::LlzkContext::new(); - common::llzk::llzk_test( + zcash_common::llzk::llzk_test( $circuit, - common::llzk::llzk_params(&ctx), + zcash_common::llzk::llzk_params(&ctx), $ir_params, $expected, false, @@ -80,11 +85,11 @@ macro_rules! basic_llzk_test { #[test] fn opt() { - common::setup(); + zcash_common::setup(); let ctx = llzk::context::LlzkContext::new(); - common::llzk::llzk_test( + zcash_common::llzk::llzk_test( $circuit, - common::llzk::opt_llzk_params(&ctx), + zcash_common::llzk::opt_llzk_params(&ctx), $ir_params, $expected_opt, true, @@ -94,12 +99,12 @@ macro_rules! basic_llzk_test { } }; ($name:ident, $circuit:expr, $expected:expr, $expected_opt:expr $(,)?) => { - $crate::common::llzk::basic_llzk_test! { + $crate::zcash_common::llzk::basic_llzk_test! { $name, $circuit, $expected, $expected_opt, - halo2_llzk_frontend::ir::generate::IRGenParamsBuilder::new().build() + haloumi::ir::r#gen::IRGenParams::new() } }; } diff --git a/driver/tests/zcash_common/mod.rs b/driver/tests/zcash_common/mod.rs new file mode 100644 index 0000000..3459994 --- /dev/null +++ b/driver/tests/zcash_common/mod.rs @@ -0,0 +1,165 @@ +use ff::{Field, PrimeField}; +use haloumi::{ + ir::r#gen::gates::{GateScope, callbacks::GateCallbacks, rewrite::GateRewritePattern}, + ir::r#gen::{IRGenParams, circuit::resolved::ResolvedIRCircuit}, +}; +use haloumi_ir_gen::gates::rewrite::{Match, MatchResult}; +use zcash_halo2_proofs::{ + dev::haloumi::{Haloumi, SynthesizableCircuit}, + plonk::Expression, +}; + +pub mod llzk; +pub mod picus; + +pub fn setup() { + let _ = simplelog::TestLogger::init(log::LevelFilter::Debug, simplelog::Config::default()); +} + +#[macro_export] +macro_rules! ensure_validation { + ($x:expr) => {{ + $x.validate().expect("Test failed due to validation errors"); + }}; +} + +/// We run the synthesis separately to test that the lifetimes of the values +/// can be untied to the CircuitSynthesis struct. But also if we want to add LLZK tests +/// this makes sure to test the retargeability of the driver. +pub fn synthesize_and_generate_ir( + driver: &mut Haloumi, + circuit: C, + params: IRGenParams>, +) -> ResolvedIRCircuit +where + F: PrimeField + std::cmp::Ord, + C: SynthesizableCircuit, +{ + let syn = driver.synthesize(&circuit).unwrap(); + let unresolved = driver.generate_ir(&syn, params).unwrap(); + ensure_validation!(unresolved); + let resolved = unresolved.resolve().unwrap(); + ensure_validation!(resolved); + resolved +} + +fn common_lowering( + circuit: C, + driver: &mut Haloumi, + ir_params: IRGenParams>, + canonicalize: bool, +) -> ResolvedIRCircuit +where + F: PrimeField + std::cmp::Ord, + C: SynthesizableCircuit, +{ + let mut resolved = synthesize_and_generate_ir(driver, circuit, ir_params); + if canonicalize { + resolved.constant_fold().unwrap(); + ensure_validation!(resolved); + resolved.canonicalize(); + ensure_validation!(resolved); + } + resolved +} + +fn clean_string(s: &str) -> String { + let mut r = String::with_capacity(s.len()); + for line in s.lines() { + let line = line.trim(); + if line.starts_with(";") || line.is_empty() { + continue; + } + let line = match line.find(';') { + Some(idx) => &line[..idx], + None => line, + } + .trim(); + + r.push_str(line); + r.push('\n'); + } + r +} + +#[allow(dead_code)] +struct DummyPattern; + +impl GateRewritePattern> for DummyPattern { + fn match_gate<'a>(&self, _gate: GateScope<'a, '_, F, Expression>) -> MatchResult + where + F: Field, + { + Ok(Match::NoMatch) + } +} + +#[allow(dead_code)] +pub struct GC; + +impl GateCallbacks> for GC { + fn patterns(&self) -> Vec>>> + where + F: Field, + { + vec![Box::new(DummyPattern)] + } +} + +macro_rules! synthesis_impl { + ($name:ident, $circuit:ty, $inputs:expr, $outputs:expr) => { + #[derive(Default)] + struct $name($circuit); + + impl zcash_halo2_proofs::dev::haloumi::SynthesizableCircuit + for $name + { + fn advice_io( + _: &Self::Config, + ) -> anyhow::Result + { + Ok(haloumi::synthesis::io::CircuitIO::empty()) + } + fn instance_io( + config: &Self::Config, + ) -> Result { + haloumi::synthesis::io::CircuitIO::new::< + zcash_halo2_proofs::plonk::Column, + >( + &[(config.instance.into(), &$inputs)], + &[(config.instance.into(), &$outputs)], + ) + } + } + + impl zcash_halo2_proofs::plonk::Circuit for $name { + type Config = + <$circuit as zcash_halo2_proofs::plonk::Circuit>::Config; + type FloorPlanner = <$circuit as zcash_halo2_proofs::plonk::Circuit< + halo2curves::bn256::Fr, + >>::FloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure( + meta: &mut zcash_halo2_proofs::plonk::ConstraintSystem, + ) -> Self::Config { + <$circuit as zcash_halo2_proofs::plonk::Circuit>::configure( + meta, + ) + } + + fn synthesize( + &self, + config: Self::Config, + layouter: impl zcash_halo2_proofs::circuit::Layouter, + ) -> Result<(), zcash_halo2_proofs::plonk::Error> { + self.0.synthesize(config, layouter) + } + } + }; +} + +pub(crate) use synthesis_impl; diff --git a/driver/tests/tests/common/picus.rs b/driver/tests/zcash_common/picus.rs similarity index 62% rename from driver/tests/tests/common/picus.rs rename to driver/tests/zcash_common/picus.rs index 8ae1300..1e2bae1 100644 --- a/driver/tests/tests/common/picus.rs +++ b/driver/tests/zcash_common/picus.rs @@ -1,13 +1,11 @@ #[cfg(feature = "picus-backend")] mod inner { - use crate::common::{clean_string, common_lowering}; + use crate::zcash_common::{clean_string, common_lowering}; use ff::PrimeField; - use halo2_llzk_frontend::{ - CircuitSynthesis, PicusParams, PicusParamsBuilder, - driver::Driver, - ir::{ResolvedIRCircuit, generate::IRGenParams}, - }; - use halo2_midnight_integration::plonk::{_Expression, ConstraintSystem}; + use haloumi::{ir::r#gen::IRGenParams, ir::r#gen::circuit::resolved::ResolvedIRCircuit}; + use haloumi_picus::{PicusParams, PicusParamsBuilder}; + use zcash_halo2_proofs::dev::haloumi::{Haloumi, SynthesizableCircuit}; + use zcash_halo2_proofs::plonk::Expression; pub fn picus_params() -> PicusParams { PicusParamsBuilder::new() @@ -23,25 +21,31 @@ mod inner { pub fn picus_test( circuit: C, params: PicusParams, - ir_params: IRGenParams>, + ir_params: IRGenParams>, expected: impl AsRef, canonicalize: bool, ) where F: PrimeField + std::cmp::Ord, - C: CircuitSynthesis>, + C: SynthesizableCircuit, { - let mut driver = Driver::default(); + let mut driver = Haloumi::default(); let resolved = common_lowering(circuit, &mut driver, ir_params, canonicalize); check_picus(&driver, &resolved, params, expected); } pub fn check_picus( - driver: &Driver, + driver: &Haloumi, circuit: &ResolvedIRCircuit, params: PicusParams, expected: impl AsRef, ) { - let output = clean_string(&driver.picus(circuit, params).unwrap().display().to_string()); + let output = clean_string( + &driver + .generate_picus(circuit, params) + .unwrap() + .display() + .to_string(), + ); let expected = clean_string(expected.as_ref()); similar_asserts::assert_eq!(expected, output); } @@ -55,14 +59,14 @@ macro_rules! basic_picus_test { ($name:ident, $circuit:expr, $expected:expr, $expected_opt:expr, $ir_params:expr $(,)?) => { paste::paste! { #[cfg(feature = "picus-backend")] - mod [< $name _picus >] { + mod [] { use super::*; #[test] fn no_opt() { - common::setup(); - common::picus::picus_test( + zcash_common::setup(); + zcash_common::picus::picus_test( $circuit, - common::picus::picus_params(), + zcash_common::picus::picus_params(), $ir_params, $expected, false, @@ -71,10 +75,10 @@ macro_rules! basic_picus_test { #[test] fn opt() { - common::setup(); - common::picus::picus_test( + zcash_common::setup(); + zcash_common::picus::picus_test( $circuit, - common::picus::opt_picus_params(), + zcash_common::picus::opt_picus_params(), $ir_params, $expected_opt, true, @@ -84,12 +88,12 @@ macro_rules! basic_picus_test { } }; ($name:ident, $circuit:expr, $expected:expr, $expected_opt:expr $(,)?) => { - $crate::common::picus::basic_picus_test! { + $crate::zcash_common::picus::basic_picus_test! { $name, $circuit, $expected, $expected_opt, - halo2_llzk_frontend::ir::generate::IRGenParamsBuilder::new().build() + haloumi::ir::r#gen::IRGenParams::new() } }; } diff --git a/driver/tests/tests/fibonacci_tests.rs b/driver/tests/zcash_fibonacci_tests.rs similarity index 84% rename from driver/tests/tests/fibonacci_tests.rs rename to driver/tests/zcash_fibonacci_tests.rs index b452cfc..3ec7ed4 100644 --- a/driver/tests/tests/fibonacci_tests.rs +++ b/driver/tests/zcash_fibonacci_tests.rs @@ -1,8 +1,8 @@ -use common::{picus::basic_picus_test, synthesis_impl}; -use halo2_test_circuits::fibonacci; use halo2curves::bn256::Fr; +use haloumi_zcash_test_circuits::fibonacci; +use zcash_common::{picus::basic_picus_test, synthesis_impl}; -mod common; +mod zcash_common; basic_picus_test! { fibonacci_circuit, diff --git a/driver/tests/lookup_tests.rs b/driver/tests/zcash_lookup_tests.rs similarity index 78% rename from driver/tests/lookup_tests.rs rename to driver/tests/zcash_lookup_tests.rs index da44d19..ace9a8c 100644 --- a/driver/tests/lookup_tests.rs +++ b/driver/tests/zcash_lookup_tests.rs @@ -1,22 +1,22 @@ -#[cfg(feature = "picus-backend")] -use common::picus::basic_picus_test; -use common::synthesis_impl; use group::ff::Field; use halo2curves::bn256::Fr; use haloumi::{ - ir_gen::IRGenParams, - ir_gen::lookups::callbacks::LookupCallbacks, - ir_gen::lookups::table::LookupTableGenerator, - ir_gen::temps::{ExprOrTemp, Temps}, + ir::r#gen::IRGenParams, + ir::r#gen::lookups::callbacks::LookupCallbacks, + ir::r#gen::lookups::table::LookupTableGenerator, + ir::r#gen::temps::{ExprOrTemp, Temps}, synthesis::lookups::Lookup, }; use haloumi_ir::stmt::IRStmt; use haloumi_ir_gen::lookups::callbacks::LookupError; -use haloumi_midnight_integration::plonk::_Expression; -use haloumi_test_circuits::lookup; +use haloumi_zcash_test_circuits::lookup; use std::borrow::Cow; +#[cfg(feature = "picus-backend")] +use zcash_common::picus::basic_picus_test; +use zcash_common::synthesis_impl; +use zcash_halo2_proofs::plonk::Expression; -mod common; +mod zcash_common; basic_picus_test! { lookup_circuit, @@ -76,13 +76,13 @@ synthesis_impl!( struct LookupCallbackHandler; -impl LookupCallbacks> for LookupCallbackHandler { +impl LookupCallbacks> for LookupCallbackHandler { fn on_lookup<'a>( &self, - _lookup: &'a Lookup<_Expression>, + _lookup: &'a Lookup>, _table: &dyn LookupTableGenerator, _temps: &mut Temps, - ) -> Result>>>, LookupError> { + ) -> Result>>>, LookupError> { Ok(IRStmt::comment("Ignored lookup")) } } diff --git a/driver/tests/mul_tests.rs b/driver/tests/zcash_mul_tests.rs similarity index 77% rename from driver/tests/mul_tests.rs rename to driver/tests/zcash_mul_tests.rs index b82cb5c..177a1bb 100644 --- a/driver/tests/mul_tests.rs +++ b/driver/tests/zcash_mul_tests.rs @@ -1,11 +1,11 @@ -use common::llzk::basic_llzk_test; -use common::picus::basic_picus_test; -use common::synthesis_impl; use halo2curves::bn256::Fr; -use haloumi::ir_gen::IRGenParams; -use haloumi_test_circuits::mul; +use haloumi::ir::r#gen::IRGenParams; +use haloumi_zcash_test_circuits::mul; +use zcash_common::llzk::basic_llzk_test; +use zcash_common::picus::basic_picus_test; +use zcash_common::synthesis_impl; -mod common; +mod zcash_common; basic_picus_test! { mul_circuit, @@ -31,7 +31,7 @@ basic_picus_test! { basic_picus_test! { mul_fixed, MulFixedConstraintCircuitSynthesis::default(), - include_str!("expected/picus/mul_with_fixed_constraint.picus"), + include_str!("expected/picus/mul_with_fixed_constraint_zcash.picus"), include_str!("expected/picus/mul_with_fixed_constraint_opt.picus") } @@ -84,41 +84,40 @@ basic_picus_test! { MulCircuitSynthesis::default(), include_str!("expected/picus/mul_with_rewriter.picus"), include_str!("expected/picus/mul_with_rewriter_opt.picus"), - IRGenParams::new().gate_callbacks(&common::GC) + IRGenParams::new().gate_callbacks(&zcash_common::GC) } #[cfg(feature = "picus-backend")] mod mul_inject { use crate::ensure_validation; - use haloumi::{ - driver::Driver, - ir_gen::{IRGenParams, circuit::resolved::ResolvedIRCircuit, expressions::ExpressionInRow}, - synthesis::CircuitSynthesis, + use haloumi::ir::r#gen::{ + IRGenParams, circuit::resolved::ResolvedIRCircuit, expressions::ExpressionInRow, + }; + use haloumi_core::{ + info_traits::CreateQuery as _, query::Advice as Adv, table::Column as Col, + table::RegionIndex, }; - use haloumi_core::table::RegionIndex; use haloumi_ir::{CmpOp, stmt::IRStmt}; - use haloumi_midnight_integration::halo2_proofs::plonk::Expression; - use haloumi_midnight_integration::plonk::_Expression; - use haloumi_midnight_integration::plonk::ConstraintSystem; + use zcash_halo2_proofs::plonk::AdviceQuery; + use zcash_halo2_proofs::plonk::{Circuit, ConstraintSystem}; + use zcash_halo2_proofs::{dev::haloumi::Haloumi, plonk::Expression}; use super::*; const EXPECTED_PICUS: &str = include_str!("expected/picus/mul_inject.picus"); const EXPECTED_OPT_PICUS: &str = include_str!("expected/picus/mul_inject_opt.picus"); - fn ir_to_inject<'e>() -> Vec<( - RegionIndex, - IRStmt, Fr>>, - )> { + type InjectedIR<'e> = (RegionIndex, IRStmt, Fr>>); + + fn ir_to_inject<'e>() -> Vec> { let mut cs = ConstraintSystem::::default(); let config = MulInjectCircuitSynthesis::configure(&mut cs); - let a = config.col_a.cur(); + let a = AdviceQuery::query_expr(Col::::from(config.col_a).index(), 0); let hundrend = Expression::Constant(Fr::from(1000)); let stmts = [ IRStmt::constraint(CmpOp::Lt, a.clone(), hundrend.clone()) - .map(&mut |e| ExpressionInRow::new(0, _Expression::from(e))), - IRStmt::constraint(CmpOp::Ge, a, hundrend) - .map(&mut |e| ExpressionInRow::new(1, _Expression::from(e))), + .map(&mut |e| ExpressionInRow::new(0, e)), + IRStmt::constraint(CmpOp::Ge, a, hundrend).map(&mut |e| ExpressionInRow::new(1, e)), ]; let mut injected = vec![]; @@ -133,7 +132,7 @@ mod mul_inject { injected } - fn generate_ir(driver: &mut Driver) -> ResolvedIRCircuit { + fn generate_ir(driver: &mut Haloumi) -> ResolvedIRCircuit { let circuit = MulInjectCircuitSynthesis::default(); let syn = driver.synthesize(&circuit).unwrap(); @@ -148,22 +147,22 @@ mod mul_inject { #[test] fn picus() { - common::setup(); - let mut driver = Driver::default(); + zcash_common::setup(); + let mut driver = Haloumi::default(); let resolved = generate_ir(&mut driver); - common::picus::check_picus( + zcash_common::picus::check_picus( &driver, &resolved, - common::picus::picus_params(), + zcash_common::picus::picus_params(), EXPECTED_PICUS, ); } #[test] fn opt_picus() { - common::setup(); - let mut driver = Driver::default(); + zcash_common::setup(); + let mut driver = Haloumi::default(); let mut resolved = generate_ir(&mut driver); resolved.constant_fold().unwrap(); @@ -171,10 +170,10 @@ mod mul_inject { resolved.canonicalize(); ensure_validation!(resolved); - common::picus::check_picus( + zcash_common::picus::check_picus( &driver, &resolved, - common::picus::opt_picus_params(), + zcash_common::picus::opt_picus_params(), EXPECTED_OPT_PICUS, ); } diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..dd03c4f --- /dev/null +++ b/flake.lock @@ -0,0 +1,242 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1652776076, + "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "type": "github" + }, + "original": { + "owner": "numtide", + "ref": "v1.0.0", + "repo": "flake-utils", + "type": "github" + } + }, + "llzk-lib": { + "inputs": { + "flake-utils": [ + "llzk-rs-pkgs", + "llzk-pkgs", + "flake-utils" + ], + "llzk-pkgs": [ + "llzk-rs-pkgs", + "llzk-pkgs" + ], + "nixpkgs": [ + "llzk-rs-pkgs", + "llzk-pkgs", + "nixpkgs" + ], + "pcl-mlir-pkg": [ + "llzk-rs-pkgs", + "pcl-mlir-pkg" + ], + "release-helpers": "release-helpers" + }, + "locked": { + "lastModified": 1783006155, + "narHash": "sha256-CN7GctvQUZByT6c+V3UmcvDzIruxg/QOtAA4LA/EBL0=", + "owner": "project-llzk", + "repo": "llzk-lib", + "rev": "e04f4f632269af0985c4e5eb1d7f0046c5b7084f", + "type": "github" + }, + "original": { + "owner": "project-llzk", + "repo": "llzk-lib", + "type": "github" + } + }, + "llzk-pkgs": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1778767410, + "narHash": "sha256-1BPcnOfruj+hudFV9JJ2ieio21h3cWT9VTOr0scMzU8=", + "owner": "project-llzk", + "repo": "llzk-nix-pkgs", + "rev": "aab16d7fa4a4d498f1dab9a8ea95b4e571b50b44", + "type": "github" + }, + "original": { + "owner": "project-llzk", + "repo": "llzk-nix-pkgs", + "type": "github" + } + }, + "llzk-rs-pkgs": { + "inputs": { + "flake-utils": [ + "llzk-pkgs", + "flake-utils" + ], + "llzk-lib": "llzk-lib", + "llzk-pkgs": [ + "llzk-pkgs" + ], + "nixpkgs": [ + "llzk-pkgs", + "nixpkgs" + ], + "pcl-mlir-pkg": "pcl-mlir-pkg", + "release-helpers": [ + "llzk-rs-pkgs", + "llzk-lib", + "release-helpers" + ], + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1783006533, + "narHash": "sha256-5BFBoWPZm+TRVPtwmw2uVbYjPVbXBlEXIeAVZ0GCN5E=", + "owner": "project-llzk", + "repo": "llzk-rs", + "rev": "7f6467d9480c34aa0f668259a69250f26966eee0", + "type": "github" + }, + "original": { + "owner": "project-llzk", + "repo": "llzk-rs", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1761656231, + "narHash": "sha256-EiED5k6gXTWoAIS8yQqi5mAX6ojnzpHwAQTS3ykeYMg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e99366c665bdd53b7b500ccdc5226675cfc51f45", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pcl-mlir-pkg": { + "inputs": { + "flake-utils": [ + "llzk-rs-pkgs", + "llzk-pkgs", + "flake-utils" + ], + "nixpkgs": [ + "llzk-rs-pkgs", + "llzk-pkgs", + "nixpkgs" + ], + "release-helpers": [ + "llzk-rs-pkgs", + "release-helpers" + ], + "shared-pkgs": [ + "llzk-rs-pkgs", + "llzk-pkgs" + ] + }, + "locked": { + "lastModified": 1762544039, + "narHash": "sha256-Esd4SAzUt5G3esTa6fTmivKpRScEROwSME4nN/SAU4w=", + "owner": "Veridise", + "repo": "pcl-mlir", + "rev": "55cf619b032314198aacafc305871fb66b12b70e", + "type": "github" + }, + "original": { + "owner": "Veridise", + "repo": "pcl-mlir", + "type": "github" + } + }, + "release-helpers": { + "inputs": { + "flake-utils": [ + "llzk-rs-pkgs", + "llzk-lib", + "llzk-pkgs", + "flake-utils" + ], + "nixpkgs": [ + "llzk-rs-pkgs", + "llzk-lib", + "llzk-pkgs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1780590591, + "narHash": "sha256-nvEp8MipNTJbXjy7enB51FryvJln1Dnwg7Gydkli2ds=", + "owner": "project-llzk", + "repo": "open-source-release-helpers", + "rev": "b25a037ac3f7ae824b4cd403d651e6c3878d03cf", + "type": "github" + }, + "original": { + "owner": "project-llzk", + "repo": "open-source-release-helpers", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": [ + "llzk-pkgs", + "flake-utils" + ], + "llzk-lib": [ + "llzk-rs-pkgs", + "llzk-lib" + ], + "llzk-pkgs": "llzk-pkgs", + "llzk-rs-pkgs": "llzk-rs-pkgs", + "nixpkgs": [ + "llzk-pkgs", + "nixpkgs" + ], + "release-helpers": [ + "llzk-rs-pkgs", + "llzk-lib", + "release-helpers" + ], + "rust-overlay": [ + "llzk-rs-pkgs", + "rust-overlay" + ] + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "llzk-rs-pkgs", + "llzk-pkgs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1781850613, + "narHash": "sha256-UL/f++6fbg1MSC63NSynUVsww+DSay0N5TsbFzLZIsQ=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "4baecb43a008cd004e5220a777e1724bd8d43e43", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..38c716d --- /dev/null +++ b/flake.nix @@ -0,0 +1,96 @@ +{ + inputs = { + llzk-pkgs.url = "github:project-llzk/llzk-nix-pkgs"; + nixpkgs.follows = "llzk-pkgs/nixpkgs"; + flake-utils.follows = "llzk-pkgs/flake-utils"; + llzk-rs-pkgs = { + url = "github:project-llzk/llzk-rs"; + inputs = { + nixpkgs.follows = "llzk-pkgs/nixpkgs"; + flake-utils.follows = "llzk-pkgs/flake-utils"; + llzk-pkgs.follows = "llzk-pkgs"; + }; + }; + llzk-lib.follows = "llzk-rs-pkgs/llzk-lib"; + release-helpers.follows = "llzk-rs-pkgs/llzk-lib/release-helpers"; + rust-overlay.follows = "llzk-rs-pkgs/rust-overlay"; + }; + + # Custom colored bash prompt + nixConfig.bash-prompt = "\\[\\e[0;32m\\][haloumi]\\[\\e[m\\] \\[\\e[38;5;244m\\]\\w\\[\\e[m\\] % "; + + outputs = + { + self, + nixpkgs, + flake-utils, + release-helpers, + llzk-pkgs, + llzk-lib, + llzk-rs-pkgs, + rust-overlay, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ + (import rust-overlay) + llzk-pkgs.overlays.default + llzk-lib.overlays.default + llzk-rs-pkgs.overlays.default + release-helpers.overlays.default + ]; + }; + + haloumi = pkgs.rustPlatform.buildRustPackage ( + { + pname = "haloumi"; + version = "0.5.12"; + src = ./.; + + nativeBuildInputs = pkgs.llzkSharedEnvironment.nativeBuildInputs; + buildInputs = pkgs.llzkSharedEnvironment.devBuildInputs; + + cargoLock = { + lockFile = ./Cargo.lock; + allowBuiltinFetchGit = true; + }; + + cargoBuildFlags = [ + "--package" + "haloumi" + ]; + cargoTestFlags = [ + "--package" + "haloumi" + ]; + dontUsePytestCheck = true; + } + // pkgs.llzkSharedEnvironment.env + // pkgs.llzkSharedEnvironment.pkgSettings + ); + in + { + packages = flake-utils.lib.flattenTree { + haloumi = haloumi; + default = haloumi; + }; + + devShells = flake-utils.lib.flattenTree { + default = pkgs.mkShell ( + { + nativeBuildInputs = pkgs.llzkSharedEnvironment.nativeBuildInputs; + buildInputs = pkgs.llzkSharedEnvironment.devBuildInputs ++ [ + pkgs.nixfmt-rfc-style + pkgs.rust-bin.stable.latest.default + ]; + } + // pkgs.llzkSharedEnvironment.env + // pkgs.llzkSharedEnvironment.devSettings + ); + }; + } + ); +} diff --git a/ir-gen/src/expressions.rs b/ir-gen/src/expressions.rs index 5de1f80..bc566b5 100644 --- a/ir-gen/src/expressions.rs +++ b/ir-gen/src/expressions.rs @@ -81,7 +81,7 @@ impl<'e, E: Clone, F> ExpressionInRow<'e, E, F> { } /// Creates a [`ScopedExpression`] scoped by a - /// [`RegionRow`](crate::regions::region_row::RegionRow). + /// [`RegionRow`]. pub(crate) fn scoped_in_region_row<'r>( self, region: RegionData<'r>, diff --git a/ir-gen/src/regions/row.rs b/ir-gen/src/regions/row.rs index 91e5075..e6324c4 100644 --- a/ir-gen/src/regions/row.rs +++ b/ir-gen/src/regions/row.rs @@ -91,7 +91,7 @@ impl<'io, 'fq, F: Field> Row<'io, 'fq, F> { /// Resolves the query of the given column type. /// - /// If the cell was detected as part of the IO returns [`FuncIO::Arg`] or [`FuncIO::Field`]. + /// If the cell was detected as part of the IO returns [`FuncIO::Arg`] or [`FuncIO::Output`]. /// Otherwise returns the fallback value if given. Otherwise fails. fn resolve( &self, diff --git a/ir/src/stmt.rs b/ir/src/stmt.rs index 9b9b3a9..3cc6c63 100644 --- a/ir/src/stmt.rs +++ b/ir/src/stmt.rs @@ -103,8 +103,10 @@ impl PartialEq for IRStmt { /// inside. /// /// For example: + /// ```text /// Seq([a, Seq([b, c])]) == Seq([a, b, c]) /// a == Seq([a]) + /// ``` fn eq(&self, other: &Self) -> bool { std::iter::zip(self.iter(), other.iter()).all(|(lhs, rhs)| match (&lhs.0, &rhs.0) { (IRStmtImpl::ConstraintCall(lhs), IRStmtImpl::ConstraintCall(rhs)) => lhs.eq(rhs), @@ -229,7 +231,7 @@ impl IRStmt { /// Prepends a comment to the statement. pub fn with_comment(self, comment: String) -> Self { - let meta = self.1.clone(); + let meta = self.1; Self( IRStmtImpl::BlockComment(BlockComment::new(Some(comment), self)), meta, diff --git a/ir/src/stmt/cond_block.rs b/ir/src/stmt/cond_block.rs index 6bff4a0..f2adf2a 100644 --- a/ir/src/stmt/cond_block.rs +++ b/ir/src/stmt/cond_block.rs @@ -141,100 +141,3 @@ where } } } - -#[cfg(test)] -mod tests { - use haloumi_core::{felt::Felt, slot::arg::ArgNo}; - use rstest::{fixture, rstest}; - - use crate::expr::IRAexpr; - - use super::*; - - type Stmt = IRStmt; - type Bexpr = IRBexpr; - - fn true_bexpr() -> Bexpr { - true.into() - } - - fn false_bexpr() -> Bexpr { - false.into() - } - - fn truthy_const_bexpr1() -> Bexpr { - let one = IRAexpr::constant(Felt::new(BabyBear::from(1))); - let ten = IRAexpr::constant(Felt::new(BabyBear::from(10))); - let eleven = IRAexpr::constant(Felt::new(BabyBear::from(11))); - Bexpr::eq(one + ten, eleven) - } - - fn falshy_const_bexpr1() -> Bexpr { - let one = IRAexpr::constant(Felt::new(BabyBear::from(1))); - let ten = IRAexpr::constant(Felt::new(BabyBear::from(10))); - let twelve = IRAexpr::constant(Felt::new(BabyBear::from(12))); - Bexpr::eq(one + ten, twelve) - } - - fn non_const_bexpr1() -> Bexpr { - let one = IRAexpr::constant(Felt::new(BabyBear::from(1))); - let arg0 = IRAexpr::slot(ArgNo::from(0)); - let eleven = IRAexpr::constant(Felt::new(BabyBear::from(11))); - Bexpr::eq(one + arg0, eleven) - } - - fn test_stmt() -> Stmt { - Stmt::comment("There is an assertion below").then(Stmt::assert(truthy_const_bexpr1())) - } - - #[fixture] - fn stmt() -> Stmt { - test_stmt() - } - - #[rstest] - #[case(true_bexpr())] - #[case(false_bexpr())] - #[case(truthy_const_bexpr1())] - #[case(falshy_const_bexpr1())] - #[should_panic(expected = "NonConstIRBexprError")] - #[case(non_const_bexpr1())] - fn const_block_validation(stmt: Stmt, #[case] cond: Bexpr) { - let cb = CondBlock::new(cond.try_into().unwrap(), stmt); - let _ = cb.validate().unwrap(); - } - - #[rstest] - #[case(truthy_const_bexpr1())] - #[case(falshy_const_bexpr1())] - fn const_block_validation_after_map(stmt: Stmt, #[case] cond: Bexpr) { - let mut cb = CondBlock::new(cond.try_into().unwrap(), stmt); - let _ = cb.validate().unwrap(); - cb.map_inplace(&mut |e| { - *e = IRAexpr::slot(ArgNo::from(1)); - }); - let res = cb.validate(); - assert!(res.is_err()); - } - - #[rstest] - #[case(true_bexpr(), test_stmt())] - #[case(false_bexpr(), Stmt::empty())] - #[case(truthy_const_bexpr1(), test_stmt())] - #[case(falshy_const_bexpr1(), Stmt::empty())] - fn const_block_folding(stmt: Stmt, #[case] cond: Bexpr, #[case] expected: Stmt) { - let mut cb = CondBlock::new(cond.try_into().unwrap(), stmt); - let _ = cb.validate().unwrap(); - let folded = cb.constant_fold().unwrap().unwrap(); - assert_eq!(folded, expected); - } - - use ff::PrimeField; - - /// Implementation of BabyBear used for testing the [`Felt`](super::Felt) type. - #[derive(PrimeField)] - #[PrimeFieldModulus = "2013265921"] - #[PrimeFieldGenerator = "31"] - #[PrimeFieldReprEndianness = "little"] - pub struct BabyBear([u64; 1]); -} diff --git a/llzk/src/codegen.rs b/llzk/src/codegen.rs index 0525c6e..b4119ac 100644 --- a/llzk/src/codegen.rs +++ b/llzk/src/codegen.rs @@ -33,16 +33,23 @@ impl<'c, 's> LlzkCodegen<'c, 's> { &self, name: &str, io: StructIO, - is_main: bool, ) -> Result, Error> { - let s = - factory::create_struct(self.context(), name, self.struct_count.next(), io, is_main)?; - Ok(LlzkStructLowering::new(self.context(), self.add_struct(s)?)) + let s = factory::create_struct(self.state, name, self.struct_count.next(), io)?; + LlzkStructLowering::new(self.state, self.add_struct(s)?) } fn context(&self) -> &'c Context { self.state.context() } + + fn set_main_struct(&self, name: &str) { + // Because we need a mutable reference but we only have `&self`. + let mut op = unsafe { OperationRefMut::from_raw(self.module.as_operation().to_raw()) }; + op.set_attribute( + *llzk::prelude::MAIN_ATTR_NAME, + TypeAttribute::new(StructType::from_str(self.context(), name).into()).into(), + ); + } } impl<'c: 's, 's> Codegen<'c, 's> for LlzkCodegen<'c, 's> { @@ -52,7 +59,10 @@ impl<'c: 's, 's> Codegen<'c, 's> for LlzkCodegen<'c, 's> { type Error = Error; fn initialize(state: &'s Self::State) -> Self { - let module = llzk_module(Location::unknown(state.context())); + let mut module = llzk_module(Location::unknown(state.context()), Some("halo2")); + if let Some(spec) = state.spec() { + module.add_field_spec(spec); + } Self { state, module, @@ -67,7 +77,8 @@ impl<'c: 's, 's> Codegen<'c, 's> for LlzkCodegen<'c, 's> { ) -> Result { let name = self.state.params().top_level().unwrap_or("Main"); log::debug!("Creating Main struct with name '{name}'"); - self.create_lowering_scope(name, StructIO::from_io(advice_io, instance_io), true) + self.set_main_struct(name); + self.create_lowering_scope(name, StructIO::from_io(advice_io, instance_io)) } fn define_function( @@ -76,7 +87,7 @@ impl<'c: 's, 's> Codegen<'c, 's> for LlzkCodegen<'c, 's> { inputs: usize, outputs: usize, ) -> Result { - self.create_lowering_scope(name, StructIO::from_io_count(inputs, outputs), false) + self.create_lowering_scope(name, StructIO::from_io_count(inputs, outputs)) } fn on_scope_end(&self, _: Self::FuncOutput) -> Result<(), Self::Error> { @@ -84,8 +95,6 @@ impl<'c: 's, 's> Codegen<'c, 's> for LlzkCodegen<'c, 's> { } fn generate_output(mut self) -> Result { - let signal = r#struct::helpers::define_signal_struct(self.context())?; - self.module.body().insert_operation(0, signal.into()); verify_operation_with_diags(&self.module.as_operation()).map_err(|err| { Error::VerificationFailed { err, @@ -110,13 +119,13 @@ fn create_pipeline(context: &Context) -> PassManager<'_> { let pm = PassManager::new(context); pm.nested_under("builtin.module") .nested_under("struct.def") - .add_pass(llzk_passes::create_field_write_validator_pass()); + .add_pass(llzk_passes::create_member_write_validator_pass()); pm.add_pass(melior_passes::create_canonicalizer()); pm.add_pass(melior_passes::create_cse()); pm.add_pass(llzk_passes::create_redundant_read_and_write_elimination_pass()); pm.nested_under("builtin.module") .nested_under("struct.def") - .add_pass(llzk_passes::create_field_write_validator_pass()); + .add_pass(llzk_passes::create_member_write_validator_pass()); let opm = pm.as_operation_pass_manager(); log::debug!("Optimization pipeline: {opm}"); diff --git a/llzk/src/error.rs b/llzk/src/error.rs index 2fb7118..4b8cbe4 100644 --- a/llzk/src/error.rs +++ b/llzk/src/error.rs @@ -12,6 +12,15 @@ pub enum Error { /// Raised when an output is missing. #[error("Struct is missing output #{0}")] MissingOutput(FieldId), + /// Raised when an call's member is missing. + #[error("Struct is missing callee #{0}")] + MissingCalleeMember(usize), + /// Raised when an call's member output is missing. + #[error("Struct is missing callee's #{0} output #{1}")] + MissingCalleeMemberOutput(usize, usize), + /// Raised when an call's member is missing. + #[error("Missing struct of type #{0}")] + MissingStruct(String), /// Raised if the constrain function is missing. #[error("Constrain function is missing!")] MissingConstrainFunc, @@ -41,6 +50,9 @@ pub enum Error { /// Additional context notes. note: &'static str, }, + /// Other kinds of errors. + #[error("{0}")] + Other(String), } impl From for haloumi_lowering::error::Error { diff --git a/llzk/src/factory.rs b/llzk/src/factory.rs index 1779295..46e792e 100644 --- a/llzk/src/factory.rs +++ b/llzk/src/factory.rs @@ -6,6 +6,8 @@ use melior::{ ir::{Identifier, Location, Operation, Type}, }; +use crate::state::LlzkCodegenState; + /// Generates a pseudo-filename for use in location metadata in the generated IR. pub fn filename(name: &str, section: Option<&str>) -> String { use std::fmt::Write; @@ -35,9 +37,9 @@ pub struct StructIO { impl StructIO { fn fields<'c>( &self, - context: &'c Context, + state: &LlzkCodegenState<'c>, header: &str, - ) -> impl Iterator, LlzkError>> { + ) -> impl Iterator, LlzkError>> { let public_filename = filename(header, Some("public outputs")); let private_filename = filename(header, Some("private outputs")); std::iter::repeat_n(true, self.public_outputs) @@ -49,19 +51,18 @@ impl StructIO { } else { &private_filename }; - (public, Location::new(context, filename, n, 0)) + (public, Location::new(state.context(), filename, n, 0)) }) .enumerate() .map(|(n, (public, loc))| { let name = format!("out_{n}"); - r#struct::field(loc, &name, FeltType::new(context), false, public) + dialect::r#struct::member(loc, &name, state.felt_type(), false, public) }) } pub fn args<'c>( &self, - ctx: &'c Context, - is_main: bool, + state: &LlzkCodegenState<'c>, struct_name: &str, ) -> Vec<(Type<'c>, Location<'c>)> { let public_filename = filename(struct_name, Some("public inputs")); @@ -74,14 +75,12 @@ impl StructIO { .take(self.private_inputs); let locs = public_locs .chain(private_locs) - .map(|(n, filename)| Location::new(ctx, filename, n, 0)); + .map(|(n, filename)| Location::new(state.context(), filename, n, 0)); - let ty: Type<'c> = if is_main { - StructType::from_str(ctx, "Signal").into() - } else { - FeltType::new(ctx).into() - }; - let types = std::iter::repeat_n(ty, self.public_inputs + self.private_inputs); + let types = std::iter::repeat_n( + Type::from(state.felt_type()), + self.public_inputs + self.private_inputs, + ); std::iter::zip(types, locs).collect() } @@ -110,47 +109,46 @@ impl StructIO { Self { private_inputs: inputs, public_inputs: 0, - private_outputs: outputs, - public_outputs: 0, + private_outputs: 0, + public_outputs: outputs, } } } pub fn create_struct<'c>( - context: &'c Context, + state: &LlzkCodegenState<'c>, struct_name: &str, idx: usize, io: StructIO, - is_main: bool, ) -> Result, LlzkError> { - log::debug!("context = {context:?}"); - let loc = struct_def_op_location(context, struct_name, idx); + log::debug!("context = {:?}", state.context()); + let loc = struct_def_op_location(state.context(), struct_name, idx); log::debug!("Struct location: {loc:?}"); let fields = io - .fields(context, struct_name) + .fields(state, struct_name) .map(|r| r.map(Operation::from)); - let func_args = io.args(context, is_main, struct_name); - let arg_attrs = io.arg_attrs(context); + let func_args = io.args(state, struct_name); + let arg_attrs = io.arg_attrs(state.context()); log::debug!("Creating function with arguments: {func_args:?}"); let funcs = [ - r#struct::helpers::compute_fn( + dialect::r#struct::helpers::compute_fn( loc, - StructType::from_str(context, struct_name), + StructType::from_str(state.context(), struct_name), &func_args, Some(&arg_attrs), ) .map(Operation::from), - r#struct::helpers::constrain_fn( + dialect::r#struct::helpers::constrain_fn( loc, - StructType::from_str(context, struct_name), + StructType::from_str(state.context(), struct_name), &func_args, Some(&arg_attrs), ) .map(Operation::from), ]; - r#struct::def(loc, struct_name, &[], fields.chain(funcs)) + dialect::r#struct::def(loc, struct_name, fields.chain(funcs)) } diff --git a/llzk/src/lib.rs b/llzk/src/lib.rs index fc154f7..b1aedb8 100644 --- a/llzk/src/lib.rs +++ b/llzk/src/lib.rs @@ -3,8 +3,11 @@ #![deny(missing_debug_implementations)] #![deny(missing_docs)] +use std::io::Write; + use codegen::LlzkCodegen; use haloumi_backend::Backend; +use llzk::prelude::ModuleExt; use melior::ir::Module; use state::LlzkCodegenState; @@ -33,6 +36,14 @@ impl<'c> LlzkOutput<'c> { pub fn module(&self) -> &Module<'c> { &self.module } + + /// Writes the output as bytecode. + /// + /// This method is meant for clients that need to write the result of the LLZK backend but + /// don't want to bring the `llzk` as a dependency. + pub fn dump(&self, dest: &mut dyn Write) -> std::io::Result<()> { + self.module.write_bytecode(dest) + } } impl<'c> From> for LlzkOutput<'c> { diff --git a/llzk/src/lowering.rs b/llzk/src/lowering.rs index b8f82b5..8ca9607 100644 --- a/llzk/src/lowering.rs +++ b/llzk/src/lowering.rs @@ -1,8 +1,10 @@ use crate::error::{Error, UnexpectedTypeError}; use crate::factory::filename; +use crate::state::LlzkCodegenState; //use backend_err::{Result, backend_err}; use haloumi_lowering::{ExprLowering, Lowering, Result as LoweringResult, bail_backend}; use llzk::builder::OpBuilder; +use llzk::dialect::function; use llzk::prelude::*; use melior::dialect::arith; use melior::ir::ValueLike; @@ -13,6 +15,8 @@ use melior::{ ir::{Location, Operation, OperationRef, Type, Value}, }; use mlir_sys::MlirValue; +use std::cell::RefCell; +use std::collections::HashMap; use std::rc::Rc; use super::counter::Counter; @@ -23,67 +27,134 @@ use haloumi_core::{ slot::{Slot as FuncIO, arg::ArgNo, output::OutputId as FieldId}, }; +/// Types of members the circuit could have. +enum MemberKind<'s> { + /// Advice cells. + Advice { col: usize, row: usize }, + /// Fixed cells. + Fixed { col: usize, row: usize }, + /// Subcomponents called by the circuit. + Callee { name: &'s str, id: usize }, +} + +impl MemberKind<'_> { + /// String representation of the member's name. + fn member_name(&self) -> String { + match self { + MemberKind::Advice { col, row } => format!("adv_{col}_{row}"), + MemberKind::Fixed { col, row } => format!("fix_{col}_{row}"), + MemberKind::Callee { name, id } => format!("{name}_{id}"), + } + } + + fn location<'c>(&self, context: &'c Context, struct_name: &str) -> Location<'c> { + match self { + MemberKind::Advice { col, row } => { + let filename = filename(struct_name, Some("advice cell")); + Location::new(context, &filename, *col, *row) + } + MemberKind::Fixed { col, row } => { + let filename = filename(struct_name, Some("fixed cell")); + Location::new(context, &filename, *col, *row) + } + MemberKind::Callee { name, id } => { + let filename = filename(struct_name, Some(&format!("subgroup '{name}'"))); + Location::new(context, &filename, *id, 0) + } + } + } + + fn member_type<'c>(&self, state: &LlzkCodegenState<'c>) -> Type<'c> { + match self { + MemberKind::Advice { .. } | MemberKind::Fixed { .. } => state.felt_type().into(), + MemberKind::Callee { name, .. } => StructType::from_str(state.context(), name).into(), + } + } +} + #[derive(Debug)] pub struct LlzkStructLowering<'c, 's> { - context: &'c Context, + state: &'s LlzkCodegenState<'c>, + builder: OpBuilder<'c, 'c>, struct_op: StructDefOpRefMut<'c, 's>, constraints_counter: Rc, + callees_counter: Rc, + callee_names: Rc>>, } impl<'c, 's> LlzkStructLowering<'c, 's> { - pub fn new(context: &'c Context, struct_op: StructDefOpRefMut<'c, 's>) -> Self { - Self { - context, + pub fn new( + state: &'s LlzkCodegenState<'c>, + struct_op: StructDefOpRefMut<'c, 's>, + ) -> Result { + let builder = OpBuilder::at_block_end( + state.context(), + struct_op + .constrain_func() + .ok_or(Error::MissingConstrainFunc)? + .region(0)? + .first_block() + .ok_or(Error::MissingBlock)?, + ); + Ok(Self { + state, struct_op, + builder, constraints_counter: Rc::new(Default::default()), - } + callees_counter: Rc::new(Default::default()), + callee_names: Rc::new(Default::default()), + }) } fn context(&self) -> &'c Context { - self.context + self.state.context() } - fn struct_name(&self) -> &str { - StructDefOpLike::name(&self.struct_op) + fn builder(&self) -> &OpBuilder<'c, 'c> { + &self.builder } - fn get_cell_field( - &self, - kind: &str, - col: usize, - row: usize, - ) -> Result, Error> { - let name = format!("{kind}_{col}_{row}"); - Ok(self.struct_op.get_or_create_field_def(&name, || { - let filename = filename(self.struct_name(), Some("advice cell")); - let loc = Location::new(self.context(), &filename, col, row); - r#struct::field(loc, &name, FeltType::new(self.context()), false, false) + fn struct_name(&self) -> &str { + self.struct_op.sym_name() + } + + fn get_cell_member(&self, kind: MemberKind<'_>) -> Result, Error> { + let name = kind.member_name(); + Ok(self.struct_op.find_or_create_member_def(&name, || { + log::debug!("Creating member named '@{name}'"); + dialect::r#struct::member( + kind.location(self.context(), self.struct_name()), + &name, + kind.member_type(self.state), + false, + false, + ) })?) } /// Tries to fetch an advice cell field, if it doesn't exist creates a field that represents /// it. #[inline] - fn get_adv_cell(&self, col: usize, row: usize) -> Result, Error> { - self.get_cell_field("adv", col, row) + fn get_adv_cell(&self, col: usize, row: usize) -> Result, Error> { + self.get_cell_member(MemberKind::Advice { col, row }) } /// Tries to fetch a fixed cell field, if it doesn't exist creates a field that represents /// it. #[inline] - fn get_fix_cell(&self, col: usize, row: usize) -> Result, Error> { - self.get_cell_field("fix", col, row) + fn get_fix_cell(&self, col: usize, row: usize) -> Result, Error> { + self.get_cell_member(MemberKind::Fixed { col, row }) } - fn get_output(&self, field: FieldId) -> Result, Error> { + fn get_output(&self, field: FieldId) -> Result, Error> { self.struct_op - .get_field_def(format!("out_{field}").as_str()) + .find_member_def(format!("out_{field}").as_str()) .ok_or(Error::MissingOutput(field)) } fn get_constrain_func(&self) -> Result, Error> { self.struct_op - .get_constrain_func() + .constrain_func() .ok_or(Error::MissingConstrainFunc) } @@ -121,47 +192,52 @@ impl<'c, 's> LlzkStructLowering<'c, 's> { /// Returns the (n+1)-th argument of the constrain function. The index is offset by one because /// in the constrain function the first argument is always an instance of the struct. fn get_arg(&self, arg_no: ArgNo) -> Result, Error> { - let val = self.get_arg_impl(*arg_no + 1)?; - let signal_typ = StructType::from_str(self.context(), "Signal"); - if val.r#type() == signal_typ.into() { - let builder = OpBuilder::new(self.context()); - return self.append_expr(r#struct::readf( - &builder, - Location::unknown(self.context()), - FeltType::new(self.context()).into(), - val, - "reg", - )?); - } - Ok(val) + self.get_arg_impl(*arg_no + 1) } fn get_component(&self) -> Result, Error> { self.get_arg_impl(0) } - fn read_field(&self, field: FieldDefOpRef<'c, '_>) -> Result, Error> { - let builder = OpBuilder::new(self.context()); - - self.append_expr(r#struct::readf( - &builder, + fn read_field(&self, field: MemberDefOpRef<'c, '_>) -> Result, Error> { + self.append_expr(dialect::r#struct::readm( + self.builder(), Location::unknown(self.context()), - field.field_type(), + field.member_type(), self.get_component()?, - field.field_name(), + field.member_name(), + )?) + } + + fn read_callee_output( + &self, + field: MemberDefOpRef<'c, '_>, + callee: Value<'c, '_>, + ) -> Result, Error> { + self.append_expr(dialect::r#struct::readm( + self.builder(), + Location::unknown(self.context()), + field.member_type(), + callee, + field.member_name(), )?) } fn lower_constant_impl(&self, f: Felt) -> Result, Error> { - let const_attr = FeltConstAttribute::from_biguint(self.context(), f.as_ref()); - self.append_expr(felt::constant( + let const_attr = + FeltConstAttribute::from_biguint(self.context(), f.as_ref(), self.state.field_name()); + self.append_expr(dialect::felt::constant( Location::unknown(self.context()), const_attr, )?) } fn create_assert_op(&self, expr: Value<'c, '_>) -> Result, Error> { - Ok(bool::assert(Location::unknown(self.context()), expr, None)?) + Ok(dialect::bool::assert( + Location::unknown(self.context()), + expr, + None, + )?) } fn create_bin_op( @@ -225,7 +301,7 @@ impl Lowering for LlzkStructLowering<'_, '_> { ); let cond = match op { CmpOp::Eq => { - self.append_op(constrain::eq(loc, lhs.into(), rhs.into()))?; + self.append_op(dialect::constrain::eq(loc, lhs.into(), rhs.into()))?; return Ok(()); } CmpOp::Lt => self.lower_lt(lhs, rhs), @@ -247,7 +323,7 @@ impl Lowering for LlzkStructLowering<'_, '_> { o.name() .as_string_ref() .as_str() - .map(|op_name| matches!(op_name, "constrain.eq")) + .map(|op_name| matches!(op_name, "constrain.eq" | "bool.assert")) .unwrap_or_default() }) .count() @@ -263,14 +339,29 @@ impl Lowering for LlzkStructLowering<'_, '_> { fn generate_call( &self, - _name: &str, - _inputs: &[Self::CellOutput], + name: &str, + inputs: &[Self::CellOutput], _outputs: &[FuncIO], ) -> LoweringResult<()> { - // 1. Define a field of the type of the struct that is going to be called - // 2. Load the field into a value - // 3. Call the constrain function - todo!() + let id = self.callees_counter.next(); + let kind = MemberKind::Callee { name, id }; + self.callee_names.borrow_mut().insert(id, name.to_owned()); + let args = std::iter::once(self.read_field(self.get_cell_member(kind)?)?) + .chain(inputs.iter().map(|i| i.into())) + .collect::>(); + let ret: [Type; 0] = []; + + self.append_op( + function::call( + self.builder(), + Location::unknown(self.context()), + SymbolRefAttribute::new_from_str(self.context(), name, &[&FUNC_NAME_CONSTRAIN]), + &args, + &ret, + ) + .map_err(Error::Llzk)?, + )?; + Ok(()) } fn generate_assume_deterministic(&self, _func_io: FuncIO) -> LoweringResult<()> { @@ -299,10 +390,10 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { rhs: &Self::CellOutput, ) -> LoweringResult { wrap! { - self.append_expr(self.create_bin_op(felt::add, - lhs.into(), - rhs.into(), - )?) + self.append_expr(self.create_bin_op(dialect::felt::add, + lhs.into(), + rhs.into(), + )?) } } @@ -312,7 +403,7 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { rhs: &Self::CellOutput, ) -> LoweringResult { wrap! { - self.append_expr(self.create_bin_op(felt::mul, + self.append_expr(self.create_bin_op(dialect::felt::mul, lhs.into(), rhs.into(), )?) @@ -320,7 +411,7 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { } fn lower_neg(&self, expr: &Self::CellOutput) -> LoweringResult { - wrap! { self.append_expr(self.create_un_op(felt::neg, expr.into())?) } + wrap! { self.append_expr(self.create_un_op(dialect::felt::neg, expr.into())?) } } fn lower_constant(&self, f: Felt) -> LoweringResult { @@ -332,7 +423,7 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { lhs: &Self::CellOutput, rhs: &Self::CellOutput, ) -> LoweringResult { - wrap!(self.append_expr(self.create_bin_op(bool::eq, lhs.into(), rhs.into())?)) + wrap!(self.append_expr(self.create_bin_op(dialect::bool::eq, lhs.into(), rhs.into())?)) } fn lower_and( @@ -340,7 +431,7 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { lhs: &Self::CellOutput, rhs: &Self::CellOutput, ) -> LoweringResult { - wrap!(self.append_expr(self.create_bin_op(bool::and, lhs.into(), rhs.into())?)) + wrap!(self.append_expr(self.create_bin_op(dialect::bool::and, lhs.into(), rhs.into())?)) } fn lower_or( @@ -348,7 +439,7 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { lhs: &Self::CellOutput, rhs: &Self::CellOutput, ) -> LoweringResult { - wrap!(self.append_expr(self.create_bin_op(bool::or, lhs.into(), rhs.into())?)) + wrap!(self.append_expr(self.create_bin_op(dialect::bool::or, lhs.into(), rhs.into())?)) } fn lower_function_input(&self, i: usize) -> FuncIO { @@ -373,7 +464,36 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { wrap!(self.read_field(self.get_fix_cell(cell.col(), cell.row())?)) } FuncIO::TableLookup(_, _, _, _, _) => todo!(), - FuncIO::CallOutput(_, _) => todo!(), + FuncIO::CallOutput(callee, output_idx) => { + let names = self.callee_names.borrow(); + let member_name = names + .get(&callee) + .ok_or(Error::MissingCalleeMember(callee))?; + let member = self.get_cell_member(MemberKind::Callee { + name: member_name, + id: callee, + })?; + let member_type = + StructType::try_from(member.member_type()).map_err(Error::Mlir)?; + let parent = self.struct_op.parent_operation().ok_or_else(|| { + Error::Other("expected struct op to have a parent operation".to_owned()) + })?; + let lookup = member_type + .lookup_definition(&parent) + .map_err(Error::Llzk)?; + let member_impl: StructDefOpRef = lookup + .operation() + .ok_or_else(|| Error::MissingStruct(format!("{member_type}")))? + .try_into() + .map_err(Error::Llzk)?; + + let member_output = *member_impl + .member_defs() + .get(output_idx) + .ok_or(Error::MissingCalleeMemberOutput(callee, output_idx))?; + let member_value = self.read_field(member)?; + wrap!(self.read_callee_output(member_output, member_value)) + } FuncIO::Temp(_) => todo!(), FuncIO::Challenge(_, _, _) => todo!(), } @@ -384,7 +504,7 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { lhs: &Self::CellOutput, rhs: &Self::CellOutput, ) -> LoweringResult { - wrap!(self.append_expr(self.create_bin_op(bool::lt, lhs.into(), rhs.into())?)) + wrap!(self.append_expr(self.create_bin_op(dialect::bool::lt, lhs.into(), rhs.into())?)) } fn lower_le( @@ -392,7 +512,7 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { lhs: &Self::CellOutput, rhs: &Self::CellOutput, ) -> LoweringResult { - wrap!(self.append_expr(self.create_bin_op(bool::le, lhs.into(), rhs.into())?)) + wrap!(self.append_expr(self.create_bin_op(dialect::bool::le, lhs.into(), rhs.into())?)) } fn lower_gt( @@ -400,7 +520,7 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { lhs: &Self::CellOutput, rhs: &Self::CellOutput, ) -> LoweringResult { - wrap!(self.append_expr(self.create_bin_op(bool::gt, lhs.into(), rhs.into())?)) + wrap!(self.append_expr(self.create_bin_op(dialect::bool::gt, lhs.into(), rhs.into())?)) } fn lower_ge( @@ -408,7 +528,7 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { lhs: &Self::CellOutput, rhs: &Self::CellOutput, ) -> LoweringResult { - wrap!(self.append_expr(self.create_bin_op(bool::ge, lhs.into(), rhs.into())?)) + wrap!(self.append_expr(self.create_bin_op(dialect::bool::ge, lhs.into(), rhs.into())?)) } fn lower_ne( @@ -416,11 +536,11 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { lhs: &Self::CellOutput, rhs: &Self::CellOutput, ) -> LoweringResult { - wrap!(self.append_expr(self.create_bin_op(bool::ne, lhs.into(), rhs.into())?)) + wrap!(self.append_expr(self.create_bin_op(dialect::bool::ne, lhs.into(), rhs.into())?)) } fn lower_not(&self, value: &Self::CellOutput) -> LoweringResult { - wrap!(self.append_expr(self.create_un_op(bool::not, value.into(),)?)) + wrap!(self.append_expr(self.create_un_op(dialect::bool::not, value.into(),)?)) } fn lower_true(&self) -> LoweringResult { @@ -463,8 +583,8 @@ impl ExprLowering for LlzkStructLowering<'_, '_> { .with_context("Failed to lower rhs of implies expression") ); } - let lhs = self.append_expr(self.create_un_op(bool::not, lhs)?)?; - wrap!(self.append_expr(self.create_bin_op(bool::or, lhs, rhs)?)) + let lhs = self.append_expr(self.create_un_op(dialect::bool::not, lhs)?)?; + wrap!(self.append_expr(self.create_bin_op(dialect::bool::or, lhs, rhs)?)) } fn lower_iff( @@ -551,8 +671,8 @@ mod tests { fn lower_reading_cells(fragment_main_with_cells: FragmentCfg) { fragment_test( fragment_main_with_cells, - r"%0 = struct.readf %self[@adv_1_5] : <@Main<[]>>, !felt.type - %1 = struct.readf %self[@fix_2_3] : <@Main<[]>>, !felt.type", + r"%0 = struct.readm %self[@adv_1_5] : <@Main<[]>>, !felt.type + %1 = struct.readm %self[@fix_2_3] : <@Main<[]>>, !felt.type", |l| { l.lower_funcio(FuncIO::advice_abs(1, 5))?; l.lower_funcio(FuncIO::fixed_abs(2, 3))?; @@ -563,28 +683,21 @@ mod tests { #[rstest] fn lower_sum(fragment_main: FragmentCfg) { - fragment_test( - fragment_main, - r"%0 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - %1 = felt.add %0, %0", - |l| { - let arg = l.lower_funcio(l.lower_function_input(0))?; - l.lower_sum(&arg, &arg)?; - Ok(()) - }, - ) + fragment_test(fragment_main, r"%1 = felt.add %arg1, %arg1", |l| { + let arg = l.lower_funcio(l.lower_function_input(0))?; + l.lower_sum(&arg, &arg)?; + Ok(()) + }) } #[rstest] fn lower_sum_with_io(fragment_main: FragmentCfg) { fragment_test( fragment_main, - r"%0 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - %1 = struct.readf %arg2[@reg] : <@Signal<[]>>, !felt.type - %2 = struct.readf %self[@out_0] : <@Main<[]>>, !felt.type - %3 = struct.readf %self[@out_1] : <@Main<[]>>, !felt.type - %4 = felt.add %0, %2 - %5 = felt.add %1, %3", + r"%2 = struct.readm %self[@out_0] : <@Main<[]>>, !felt.type + %3 = struct.readm %self[@out_1] : <@Main<[]>>, !felt.type + %4 = felt.add %arg1, %2 + %5 = felt.add %arg2, %3", |l| { let arg0 = l.lower_funcio(l.lower_function_input(0))?; let arg1 = l.lower_funcio(l.lower_function_input(1))?; @@ -599,114 +712,74 @@ mod tests { #[rstest] fn lower_product(fragment_main: FragmentCfg) { - fragment_test( - fragment_main, - r"%0 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - %1 = felt.mul %0, %0", - |l| { - let arg = l.lower_funcio(l.lower_function_input(0))?; - l.lower_product(&arg, &arg)?; - Ok(()) - }, - ) + fragment_test(fragment_main, r"%1 = felt.mul %arg1, %arg1", |l| { + let arg = l.lower_funcio(l.lower_function_input(0))?; + l.lower_product(&arg, &arg)?; + Ok(()) + }) } #[rstest] fn lower_neg(fragment_main: FragmentCfg) { - fragment_test( - fragment_main, - r"%0 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - %1 = felt.neg %0", - |l| { - let arg = l.lower_funcio(l.lower_function_input(0))?; - l.lower_neg(&arg)?; - Ok(()) - }, - ) + fragment_test(fragment_main, r"%1 = felt.neg %arg1", |l| { + let arg = l.lower_funcio(l.lower_function_input(0))?; + l.lower_neg(&arg)?; + Ok(()) + }) } #[rstest] fn lower_eq(fragment_main: FragmentCfg) { - fragment_test( - fragment_main, - r"%0 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - %1 = bool.cmp eq(%0, %0)", - |l| { - let arg = l.lower_funcio(l.lower_function_input(0))?; - l.lower_eq(&arg, &arg)?; - Ok(()) - }, - ) + fragment_test(fragment_main, r"%1 = bool.cmp eq(%arg1, %arg1)", |l| { + let arg = l.lower_funcio(l.lower_function_input(0))?; + l.lower_eq(&arg, &arg)?; + Ok(()) + }) } #[rstest] fn lower_lt(fragment_main: FragmentCfg) { - fragment_test( - fragment_main, - r"%0 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - %1 = bool.cmp lt(%0, %0)", - |l| { - let arg = l.lower_funcio(l.lower_function_input(0))?; - l.lower_lt(&arg, &arg)?; - Ok(()) - }, - ) + fragment_test(fragment_main, r"%1 = bool.cmp lt(%arg1, %arg1)", |l| { + let arg = l.lower_funcio(l.lower_function_input(0))?; + l.lower_lt(&arg, &arg)?; + Ok(()) + }) } #[rstest] fn lower_le(fragment_main: FragmentCfg) { - fragment_test( - fragment_main, - r"%0 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - %1 = bool.cmp le(%0, %0)", - |l| { - let arg = l.lower_funcio(l.lower_function_input(0))?; - l.lower_le(&arg, &arg)?; - Ok(()) - }, - ) + fragment_test(fragment_main, r"%1 = bool.cmp le(%arg1, %arg1)", |l| { + let arg = l.lower_funcio(l.lower_function_input(0))?; + l.lower_le(&arg, &arg)?; + Ok(()) + }) } #[rstest] fn lower_gt(fragment_main: FragmentCfg) { - fragment_test( - fragment_main, - r"%0 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - %1 = bool.cmp gt(%0, %0)", - |l| { - let arg = l.lower_funcio(l.lower_function_input(0))?; - l.lower_gt(&arg, &arg)?; - Ok(()) - }, - ) + fragment_test(fragment_main, r"%1 = bool.cmp gt(%arg1, %arg1)", |l| { + let arg = l.lower_funcio(l.lower_function_input(0))?; + l.lower_gt(&arg, &arg)?; + Ok(()) + }) } #[rstest] fn lower_ge(fragment_main: FragmentCfg) { - fragment_test( - fragment_main, - r"%0 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - %1 = bool.cmp ge(%0, %0)", - |l| { - let arg = l.lower_funcio(l.lower_function_input(0))?; - l.lower_ge(&arg, &arg)?; - Ok(()) - }, - ) + fragment_test(fragment_main, r"%1 = bool.cmp ge(%arg1, %arg1)", |l| { + let arg = l.lower_funcio(l.lower_function_input(0))?; + l.lower_ge(&arg, &arg)?; + Ok(()) + }) } #[rstest] fn lower_ne(fragment_main: FragmentCfg) { - fragment_test( - fragment_main, - r"%0 = struct.readf %arg1[@reg] : <@Signal<[]>>, !felt.type - %1 = bool.cmp ne(%0, %0)", - |l| { - let arg = l.lower_funcio(l.lower_function_input(0))?; - l.lower_ne(&arg, &arg)?; - Ok(()) - }, - ) + fragment_test(fragment_main, r"%1 = bool.cmp ne(%arg1, %arg1)", |l| { + let arg = l.lower_funcio(l.lower_function_input(0))?; + l.lower_ne(&arg, &arg)?; + Ok(()) + }) } #[rstest] @@ -957,21 +1030,17 @@ mod tests { } fn input_type_str(&self) -> &'static str { - if self.is_main { - "!struct.type<@Signal<[]>>" - } else { - "!felt.type" - } + "!felt.type" } fn cells(&self) -> String { self.advice_cells .iter() - .map(|(col, row)| format!("struct.field @adv_{col}_{row} : !felt.type\n")) + .map(|(col, row)| format!("struct.member @adv_{col}_{row} : !felt.type\n")) .chain( self.fixed_cells .iter() - .map(|(col, row)| format!("struct.field @fix_{col}_{row} : !felt.type\n")), + .map(|(col, row)| format!("struct.member @fix_{col}_{row} : !felt.type\n")), ) .collect() } @@ -980,7 +1049,7 @@ mod tests { (0..self.n_outputs).fold(String::new(), |mut acc, n| { writeln!( acc, - "struct.field @out_{n} : !felt.type{}", + "struct.member @out_{n} : !felt.type{}", if n < self.n_public_outputs { " {llzk.pub}" } else { @@ -995,9 +1064,8 @@ mod tests { fn expected_fragment(cfg: &FragmentCfg, frag: &str) -> String { format!( - r#"module attributes {{veridise.lang = "llzk"}} {{ - {signal} - struct.def @{name}<[]> {{ + r#"module attributes {{llzk.lang = "halo2", llzk.main = !struct.type<@{name}<[]>>}} {{ + struct.def @{name} {{ {fields} function.def @compute({inputs}) -> !struct.type<@{name}<[]>> attributes {{function.allow_non_native_field_ops, function.allow_witness}} {{ %{self_name} = struct.new : <@{name}<[]>> @@ -1013,7 +1081,6 @@ mod tests { name = cfg.struct_name, inputs = cfg.inputs(), fields = cfg.fields(), - signal = include_str!("test_files/signal_fragment.mlir"), self_name = cfg.self_name, cells = cfg.cells() ) diff --git a/llzk/src/params.rs b/llzk/src/params.rs index aea852a..35603ee 100644 --- a/llzk/src/params.rs +++ b/llzk/src/params.rs @@ -1,6 +1,28 @@ +use haloumi_ir::Prime; use llzk::prelude::*; use melior::Context; +/// Stores the parameters for configuring the field +/// used for the Felt types. +/// +/// Stores the name of the spec, and, if its not a +/// builtin, the prime value for defining the spec. +#[derive(Debug, Clone)] +pub struct FieldSpecParam { + name: String, + prime: Option, +} + +impl FieldSpecParam { + pub fn name(&self) -> &str { + &self.name + } + + pub fn prime(&self) -> Option { + self.prime + } +} + /// Configuration for the LLZK backend. #[derive(Clone, Debug)] pub struct LlzkParams<'c> { @@ -8,6 +30,7 @@ pub struct LlzkParams<'c> { top_level: Option, inline: bool, optimize: bool, + spec: Option, } impl<'c> LlzkParams<'c> { @@ -18,6 +41,7 @@ impl<'c> LlzkParams<'c> { top_level: Default::default(), optimize: true, inline: false, + spec: None, } } @@ -41,6 +65,11 @@ impl<'c> LlzkParams<'c> { self.optimize } + /// Returns the prime field spec, if available. + pub fn spec(&self) -> Option<&FieldSpecParam> { + self.spec.as_ref() + } + // Builder methods /// Sets the name of the top-level struct. @@ -78,4 +107,28 @@ impl<'c> LlzkParams<'c> { self.optimize = false; self } + + /// Sets the prime field spec. + pub fn with_prime_field(mut self, name: &str, prime: Prime) -> Self { + self.spec = Some(FieldSpecParam { + name: name.to_owned(), + prime: Some(prime), + }); + self + } + + /// Sets the prime field from a builtin spec. + pub fn with_builtin_field(mut self, name: &str) -> Self { + self.spec = Some(FieldSpecParam { + name: name.to_owned(), + prime: None, + }); + self + } + + /// Removes the prime field spec. + pub fn no_prime_field(mut self) -> Self { + self.spec = None; + self + } } diff --git a/llzk/src/state.rs b/llzk/src/state.rs index 090cc8a..c7ff54c 100644 --- a/llzk/src/state.rs +++ b/llzk/src/state.rs @@ -1,4 +1,5 @@ use haloumi_backend::codegen::CodegenParams; +use llzk::prelude::{FeltType, FieldSpecAttribute}; use melior::Context; use super::LlzkParams; @@ -22,6 +23,37 @@ impl<'c> LlzkCodegenState<'c> { pub fn optimize(&self) -> bool { self.params.optimize() } + + /// Returns the prime field spec if available. + /// + /// Only returns a value if the spec was configured with a custom field. If the user configured + /// the field with a builtin then this method returns `None` since there's no need for setting + /// the `llzk.fields` attribute in the resulting module. + pub fn spec(&self) -> Option> { + let spec = self.params.spec()?; + let prime = spec.prime()?; + Some(FieldSpecAttribute::from_biguint( + self.context, + spec.name(), + prime.value(), + )) + } + + /// Returns the field spec name, if available. + pub fn field_name(&self) -> Option<&str> { + self.params.spec().map(|spec| spec.name()) + } + + /// Returns the correct felt type based on the spec parameter. + /// + /// If the spec is available returns `!felt.type<"spec">` otherwise + /// returns an unspecified `!felt.type`. + pub fn felt_type(&self) -> FeltType<'c> { + match self.params.spec() { + Some(spec) => FeltType::with_field(self.context, spec.name()), + None => FeltType::new(self.context), + } + } } impl<'c> From> for LlzkCodegenState<'c> { diff --git a/llzk/src/test_files/empty_io.mlir b/llzk/src/test_files/empty_io.mlir index cff1fc0..db1e4a2 100644 --- a/llzk/src/test_files/empty_io.mlir +++ b/llzk/src/test_files/empty_io.mlir @@ -1,18 +1,5 @@ -module attributes {veridise.lang = "llzk"} { - struct.def @Signal<[]> { - struct.field @reg : !felt.type {llzk.pub} - function.def @compute(%arg0: !felt.type) -> !struct.type<@Signal<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Signal<[]>> - struct.writef %self[@reg] = %arg0 : <@Signal<[]>>, !felt.type - function.return %self : !struct.type<@Signal<[]>> - } - function.def @constrain(%arg0: !struct.type<@Signal<[]>>, %arg1: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %arg1 : !felt.type, !felt.type - function.return - } - } - struct.def @Main<[]> { +module attributes {llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>>} { + struct.def @Main { function.def @compute() -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { %self = struct.new : <@Main<[]>> function.return %self : !struct.type<@Main<[]>> diff --git a/llzk/src/test_files/mixed_io.mlir b/llzk/src/test_files/mixed_io.mlir index e4199b4..8a94d9b 100644 --- a/llzk/src/test_files/mixed_io.mlir +++ b/llzk/src/test_files/mixed_io.mlir @@ -1,27 +1,14 @@ -module attributes {veridise.lang = "llzk"} { - struct.def @Signal<[]> { - struct.field @reg : !felt.type {llzk.pub} - function.def @compute(%arg0: !felt.type) -> !struct.type<@Signal<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Signal<[]>> - struct.writef %self[@reg] = %arg0 : <@Signal<[]>>, !felt.type - function.return %self : !struct.type<@Signal<[]>> - } - function.def @constrain(%arg0: !struct.type<@Signal<[]>>, %arg1: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %arg1 : !felt.type, !felt.type - function.return - } - } - struct.def @Main<[]> { - struct.field @out_0 : !felt.type {llzk.pub} - struct.field @out_1 : !felt.type {llzk.pub} - struct.field @out_2 : !felt.type - struct.field @out_3 : !felt.type - function.def @compute(%arg0: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}, %arg1: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}, %arg2: !struct.type<@Signal<[]>>, %arg3: !struct.type<@Signal<[]>>, %arg4: !struct.type<@Signal<[]>>) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { +module attributes {llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>>} { + struct.def @Main { + struct.member @out_0 : !felt.type {llzk.pub} + struct.member @out_1 : !felt.type {llzk.pub} + struct.member @out_2 : !felt.type + struct.member @out_3 : !felt.type + function.def @compute(%arg0: !felt.type {llzk.pub = #llzk.pub}, %arg1: !felt.type {llzk.pub = #llzk.pub}, %arg2: !felt.type, %arg3: !felt.type, %arg4: !felt.type) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { %self = struct.new : <@Main<[]>> function.return %self : !struct.type<@Main<[]>> } - function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}, %arg2: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}, %arg3: !struct.type<@Signal<[]>>, %arg4: !struct.type<@Signal<[]>>, %arg5: !struct.type<@Signal<[]>>) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type {llzk.pub = #llzk.pub}, %arg2: !felt.type {llzk.pub = #llzk.pub}, %arg3: !felt.type, %arg4: !felt.type, %arg5: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { function.return } } diff --git a/llzk/src/test_files/private_inputs.mlir b/llzk/src/test_files/private_inputs.mlir index 3d9c45c..2935913 100644 --- a/llzk/src/test_files/private_inputs.mlir +++ b/llzk/src/test_files/private_inputs.mlir @@ -1,23 +1,10 @@ -module attributes {veridise.lang = "llzk"} { - struct.def @Signal<[]> { - struct.field @reg : !felt.type {llzk.pub} - function.def @compute(%arg0: !felt.type) -> !struct.type<@Signal<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Signal<[]>> - struct.writef %self[@reg] = %arg0 : <@Signal<[]>>, !felt.type - function.return %self : !struct.type<@Signal<[]>> - } - function.def @constrain(%arg0: !struct.type<@Signal<[]>>, %arg1: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %arg1 : !felt.type, !felt.type - function.return - } - } - struct.def @Main<[]> { - function.def @compute(%arg0: !struct.type<@Signal<[]>>, %arg1: !struct.type<@Signal<[]>>, %arg2: !struct.type<@Signal<[]>>) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { +module attributes {llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>>} { + struct.def @Main { + function.def @compute(%arg0: !felt.type, %arg1: !felt.type, %arg2: !felt.type) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { %self = struct.new : <@Main<[]>> function.return %self : !struct.type<@Main<[]>> } - function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !struct.type<@Signal<[]>>, %arg2: !struct.type<@Signal<[]>>, %arg3: !struct.type<@Signal<[]>>) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type, %arg2: !felt.type, %arg3: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { function.return } } diff --git a/llzk/src/test_files/private_outputs.mlir b/llzk/src/test_files/private_outputs.mlir index 8f67559..14c3905 100644 --- a/llzk/src/test_files/private_outputs.mlir +++ b/llzk/src/test_files/private_outputs.mlir @@ -1,21 +1,8 @@ -module attributes {veridise.lang = "llzk"} { - struct.def @Signal<[]> { - struct.field @reg : !felt.type {llzk.pub} - function.def @compute(%arg0: !felt.type) -> !struct.type<@Signal<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Signal<[]>> - struct.writef %self[@reg] = %arg0 : <@Signal<[]>>, !felt.type - function.return %self : !struct.type<@Signal<[]>> - } - function.def @constrain(%arg0: !struct.type<@Signal<[]>>, %arg1: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %arg1 : !felt.type, !felt.type - function.return - } - } - struct.def @Main<[]> { - struct.field @out_0 : !felt.type - struct.field @out_1 : !felt.type - struct.field @out_2 : !felt.type +module attributes {llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>>} { + struct.def @Main { + struct.member @out_0 : !felt.type + struct.member @out_1 : !felt.type + struct.member @out_2 : !felt.type function.def @compute() -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { %self = struct.new : <@Main<[]>> function.return %self : !struct.type<@Main<[]>> diff --git a/llzk/src/test_files/public_inputs.mlir b/llzk/src/test_files/public_inputs.mlir index 2aa99ec..9e702b4 100644 --- a/llzk/src/test_files/public_inputs.mlir +++ b/llzk/src/test_files/public_inputs.mlir @@ -1,23 +1,10 @@ -module attributes {veridise.lang = "llzk"} { - struct.def @Signal<[]> { - struct.field @reg : !felt.type {llzk.pub} - function.def @compute(%arg0: !felt.type) -> !struct.type<@Signal<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Signal<[]>> - struct.writef %self[@reg] = %arg0 : <@Signal<[]>>, !felt.type - function.return %self : !struct.type<@Signal<[]>> - } - function.def @constrain(%arg0: !struct.type<@Signal<[]>>, %arg1: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %arg1 : !felt.type, !felt.type - function.return - } - } - struct.def @Main<[]> { - function.def @compute(%arg0: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}, %arg1: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}, %arg2: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { +module attributes {llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>>} { + struct.def @Main { + function.def @compute(%arg0: !felt.type {llzk.pub = #llzk.pub}, %arg1: !felt.type {llzk.pub = #llzk.pub}, %arg2: !felt.type {llzk.pub = #llzk.pub}) -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { %self = struct.new : <@Main<[]>> function.return %self : !struct.type<@Main<[]>> } - function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}, %arg2: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}, %arg3: !struct.type<@Signal<[]>> {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { + function.def @constrain(%arg0: !struct.type<@Main<[]>>, %arg1: !felt.type {llzk.pub = #llzk.pub}, %arg2: !felt.type {llzk.pub = #llzk.pub}, %arg3: !felt.type {llzk.pub = #llzk.pub}) attributes {function.allow_constraint, function.allow_non_native_field_ops} { function.return } } diff --git a/llzk/src/test_files/public_outputs.mlir b/llzk/src/test_files/public_outputs.mlir index b87b176..5ba846c 100644 --- a/llzk/src/test_files/public_outputs.mlir +++ b/llzk/src/test_files/public_outputs.mlir @@ -1,21 +1,8 @@ -module attributes {veridise.lang = "llzk"} { - struct.def @Signal<[]> { - struct.field @reg : !felt.type {llzk.pub} - function.def @compute(%arg0: !felt.type) -> !struct.type<@Signal<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { - %self = struct.new : <@Signal<[]>> - struct.writef %self[@reg] = %arg0 : <@Signal<[]>>, !felt.type - function.return %self : !struct.type<@Signal<[]>> - } - function.def @constrain(%arg0: !struct.type<@Signal<[]>>, %arg1: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %arg1 : !felt.type, !felt.type - function.return - } - } - struct.def @Main<[]> { - struct.field @out_0 : !felt.type {llzk.pub} - struct.field @out_1 : !felt.type {llzk.pub} - struct.field @out_2 : !felt.type {llzk.pub} +module attributes {llzk.lang = "halo2", llzk.main = !struct.type<@Main<[]>>} { + struct.def @Main { + struct.member @out_0 : !felt.type {llzk.pub} + struct.member @out_1 : !felt.type {llzk.pub} + struct.member @out_2 : !felt.type {llzk.pub} function.def @compute() -> !struct.type<@Main<[]>> attributes {function.allow_non_native_field_ops, function.allow_witness} { %self = struct.new : <@Main<[]>> function.return %self : !struct.type<@Main<[]>> diff --git a/llzk/src/test_files/signal_fragment.mlir b/llzk/src/test_files/signal_fragment.mlir deleted file mode 100644 index eff7638..0000000 --- a/llzk/src/test_files/signal_fragment.mlir +++ /dev/null @@ -1,13 +0,0 @@ -struct.def @Signal<[]> { - struct.field @reg : !felt.type {llzk.pub} - function.def @compute(%arg0: !felt.type) -> !struct.type<@Signal<[]>> attributes {function.allow_non_native_field_ops,function.allow_witness} { - %self = struct.new : <@Signal<[]>> - struct.writef %self[@reg] = %arg0 : <@Signal<[]>>, !felt.type - function.return %self : !struct.type<@Signal<[]>> - } - function.def @constrain(%arg0: !struct.type<@Signal<[]>>, %arg1: !felt.type) attributes {function.allow_constraint, function.allow_non_native_field_ops} { - %0 = struct.readf %arg0[@reg] : <@Signal<[]>>, !felt.type - constrain.eq %0, %arg1 : !felt.type, !felt.type - function.return - } -} diff --git a/lowering/src/error.rs b/lowering/src/error.rs index 0bf593f..8828ec6 100644 --- a/lowering/src/error.rs +++ b/lowering/src/error.rs @@ -14,13 +14,13 @@ pub enum Error { /// Error emitted by implementations of [`LowerableStmt`](crate::lowerable::LowerableStmt) or /// [`LowerableExpr`](crate::lowerable::LowerableExpr). /// - /// Use [`lowering_err!`] to easily create this kind of error. + /// Use [`lowering_err!`](crate::lowering_err) to easily create this kind of error. #[error("Lowering error")] Lowering(Arc), /// Error emitted by implementations of [`Lowering`](crate::Lowering) or /// [`ExprLowering`](crate::ExprLowering). /// - /// Use [`backend_err!`] to easily create this kind of error. + /// Use [`backend_err!`](crate::backend_err) to easily create this kind of error. #[error("Backend error")] Backend(Arc), } diff --git a/support/test-circuits/Cargo.toml b/support/mdnt-test-circuits/Cargo.toml similarity index 93% rename from support/test-circuits/Cargo.toml rename to support/mdnt-test-circuits/Cargo.toml index 7bf5ea6..3ab4ecd 100644 --- a/support/test-circuits/Cargo.toml +++ b/support/mdnt-test-circuits/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "haloumi-test-circuits" +name = "haloumi-mdnt-test-circuits" categories = {workspace = true} version = {workspace = true} authors = {workspace = true} diff --git a/support/test-circuits/README.md b/support/mdnt-test-circuits/README.md similarity index 100% rename from support/test-circuits/README.md rename to support/mdnt-test-circuits/README.md diff --git a/support/test-circuits/src/fibonacci.rs b/support/mdnt-test-circuits/src/fibonacci.rs similarity index 100% rename from support/test-circuits/src/fibonacci.rs rename to support/mdnt-test-circuits/src/fibonacci.rs diff --git a/support/test-circuits/src/fibonacci/grouped.rs b/support/mdnt-test-circuits/src/fibonacci/grouped.rs similarity index 100% rename from support/test-circuits/src/fibonacci/grouped.rs rename to support/mdnt-test-circuits/src/fibonacci/grouped.rs diff --git a/support/test-circuits/src/lib.rs b/support/mdnt-test-circuits/src/lib.rs similarity index 100% rename from support/test-circuits/src/lib.rs rename to support/mdnt-test-circuits/src/lib.rs diff --git a/support/test-circuits/src/lookup.rs b/support/mdnt-test-circuits/src/lookup.rs similarity index 100% rename from support/test-circuits/src/lookup.rs rename to support/mdnt-test-circuits/src/lookup.rs diff --git a/support/test-circuits/src/lookup/two_by_three.rs b/support/mdnt-test-circuits/src/lookup/two_by_three.rs similarity index 100% rename from support/test-circuits/src/lookup/two_by_three.rs rename to support/mdnt-test-circuits/src/lookup/two_by_three.rs diff --git a/support/test-circuits/src/lookup/two_by_three_fixed.rs b/support/mdnt-test-circuits/src/lookup/two_by_three_fixed.rs similarity index 100% rename from support/test-circuits/src/lookup/two_by_three_fixed.rs rename to support/mdnt-test-circuits/src/lookup/two_by_three_fixed.rs diff --git a/support/test-circuits/src/lookup/two_by_three_zerosel.rs b/support/mdnt-test-circuits/src/lookup/two_by_three_zerosel.rs similarity index 100% rename from support/test-circuits/src/lookup/two_by_three_zerosel.rs rename to support/mdnt-test-circuits/src/lookup/two_by_three_zerosel.rs diff --git a/support/test-circuits/src/mul.rs b/support/mdnt-test-circuits/src/mul.rs similarity index 100% rename from support/test-circuits/src/mul.rs rename to support/mdnt-test-circuits/src/mul.rs diff --git a/support/test-circuits/src/mul/fixed_constraint.rs b/support/mdnt-test-circuits/src/mul/fixed_constraint.rs similarity index 100% rename from support/test-circuits/src/mul/fixed_constraint.rs rename to support/mdnt-test-circuits/src/mul/fixed_constraint.rs diff --git a/support/test-circuits/src/mul/flipped_constraint.rs b/support/mdnt-test-circuits/src/mul/flipped_constraint.rs similarity index 100% rename from support/test-circuits/src/mul/flipped_constraint.rs rename to support/mdnt-test-circuits/src/mul/flipped_constraint.rs diff --git a/support/test-circuits/src/mul/grouped.rs b/support/mdnt-test-circuits/src/mul/grouped.rs similarity index 100% rename from support/test-circuits/src/mul/grouped.rs rename to support/mdnt-test-circuits/src/mul/grouped.rs diff --git a/support/test-circuits/src/mul/grouped/deep_callstack.rs b/support/mdnt-test-circuits/src/mul/grouped/deep_callstack.rs similarity index 100% rename from support/test-circuits/src/mul/grouped/deep_callstack.rs rename to support/mdnt-test-circuits/src/mul/grouped/deep_callstack.rs diff --git a/support/test-circuits/src/mul/grouped/different_bodies.rs b/support/mdnt-test-circuits/src/mul/grouped/different_bodies.rs similarity index 100% rename from support/test-circuits/src/mul/grouped/different_bodies.rs rename to support/mdnt-test-circuits/src/mul/grouped/different_bodies.rs diff --git a/support/test-circuits/src/mul/grouped/same_body.rs b/support/mdnt-test-circuits/src/mul/grouped/same_body.rs similarity index 100% rename from support/test-circuits/src/mul/grouped/same_body.rs rename to support/mdnt-test-circuits/src/mul/grouped/same_body.rs diff --git a/support/test-circuits/src/mul/injection.rs b/support/mdnt-test-circuits/src/mul/injection.rs similarity index 100% rename from support/test-circuits/src/mul/injection.rs rename to support/mdnt-test-circuits/src/mul/injection.rs diff --git a/support/test-circuits/src/mul/recursive_groups.rs b/support/mdnt-test-circuits/src/mul/recursive_groups.rs similarity index 100% rename from support/test-circuits/src/mul/recursive_groups.rs rename to support/mdnt-test-circuits/src/mul/recursive_groups.rs diff --git a/support/test-circuits/src/mul/ten_plus_io.rs b/support/mdnt-test-circuits/src/mul/ten_plus_io.rs similarity index 100% rename from support/test-circuits/src/mul/ten_plus_io.rs rename to support/mdnt-test-circuits/src/mul/ten_plus_io.rs diff --git a/support/midnight/src/synthesizer.rs b/support/midnight/src/synthesizer.rs index a7ee39e..f56ec3a 100644 --- a/support/midnight/src/synthesizer.rs +++ b/support/midnight/src/synthesizer.rs @@ -18,7 +18,7 @@ use midnight_proofs::{ use crate::circuit::groups::_RegionsGroup; use crate::plonk::{_Advice, _Any, _Column, _Fixed, _Selector, ConstraintSystem}; -/// Implementation of [`Assignment`] compatible with [`Synthesizer`]. +/// Implementation of [`Assignment`] compatible with [`SynthesizerLike`]. #[derive(Debug)] pub struct SynthesizerAssignment<'a, F: Field, S: SynthesizerLike> { synthetizer: &'a mut S, diff --git a/support/zcash-test-circuits/Cargo.toml b/support/zcash-test-circuits/Cargo.toml new file mode 100644 index 0000000..dff0d8c --- /dev/null +++ b/support/zcash-test-circuits/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "haloumi-zcash-test-circuits" +categories = {workspace = true} +version = {workspace = true} +authors = {workspace = true} +edition = {workspace = true} +rust-version = {workspace = true} +readme = "README.md" +repository = {workspace = true} +license-file = {workspace = true} +keywords = {workspace = true} +publish = false + +[dependencies.halo2_proofs] +git = "https://github.com/project-llzk/halo2.git" +branch = "haloumi-integration" +default-features = false +features = [ + "region-groups", + "haloumi" +] + +[dependencies] +ff = {workspace = true} +anyhow = "1" + + diff --git a/support/zcash-test-circuits/README.md b/support/zcash-test-circuits/README.md new file mode 100644 index 0000000..5107087 --- /dev/null +++ b/support/zcash-test-circuits/README.md @@ -0,0 +1,3 @@ +# Circuits for end to end testing + +This crate has a collection of Halo2 circuits that are meant for doing end to end testing of Haloumi. diff --git a/support/zcash-test-circuits/src/fibonacci.rs b/support/zcash-test-circuits/src/fibonacci.rs new file mode 100644 index 0000000..7c49ed0 --- /dev/null +++ b/support/zcash-test-circuits/src/fibonacci.rs @@ -0,0 +1,180 @@ +use ff::Field; +use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner}; +use halo2_proofs::plonk::{ + Advice, Circuit, Column, ConstraintSystem, Constraints, Error, Expression, Instance, Selector, +}; +use halo2_proofs::poly::Rotation; +use std::marker::PhantomData; + +pub mod grouped; + +#[derive(Debug, Clone)] +pub struct FibonacciConfig { + pub col_a: Column, + pub col_b: Column, + pub col_c: Column, + pub selector: Selector, + pub instance: Column, +} + +pub fn fibonacci_gates(meta: &mut ConstraintSystem) -> FibonacciConfig { + let col_a = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.selector(); + let instance = meta.instance_column(); + + meta.enable_equality(col_a); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + meta.create_gate("add", |meta| { + // + // col_a | col_b | col_c | selector + // a b c s + // + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + Constraints::with_selector(Expression::Selector(selector), vec![a + b - c]) + }); + + FibonacciConfig { + col_a, + col_b, + col_c, + selector, + instance, + } +} + +#[derive(Debug, Clone)] +struct FibonacciChip { + config: FibonacciConfig, + _marker: PhantomData, +} + +impl FibonacciChip { + pub fn construct(config: FibonacciConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> FibonacciConfig { + fibonacci_gates(meta) + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + mut layouter: impl Layouter, + ) -> Result<(AssignedCell, AssignedCell, AssignedCell), Error> { + layouter.assign_region( + || "first row", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + + let a_cell = region.assign_advice_from_instance( + || "f(0)", + self.config.instance, + 0, + self.config.col_a, + 0, + )?; + + let b_cell = region.assign_advice_from_instance( + || "f(1)", + self.config.instance, + 1, + self.config.col_b, + 0, + )?; + + let c_cell = region.assign_advice( + || "a + b", + self.config.col_c, + 0, + || a_cell.value().copied() + b_cell.value(), + )?; + + Ok((a_cell, b_cell, c_cell)) + }, + ) + } + + pub fn assign_row( + &self, + mut layouter: impl Layouter, + prev_b: &AssignedCell, + prev_c: &AssignedCell, + ) -> Result, Error> { + layouter.assign_region( + || "next row", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + + // Copy the value from b & c in previous row to a & b in current row + prev_b.copy_advice(|| "a", &mut region, self.config.col_a, 0)?; + prev_c.copy_advice(|| "b", &mut region, self.config.col_b, 0)?; + + let c_cell = region.assign_advice( + || "c", + self.config.col_c, + 0, + || prev_b.value().copied() + prev_c.value(), + )?; + + Ok(c_cell) + }, + ) + } + + pub fn expose_public( + &self, + mut layouter: impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } +} + +#[derive(Default)] +pub struct FibonacciCircuit(pub PhantomData); + +impl Circuit for FibonacciCircuit { + type Config = FibonacciConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + FibonacciChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = FibonacciChip::construct(config); + + let (_, mut prev_b, mut prev_c) = + chip.assign_first_row(layouter.namespace(|| "first row"))?; + + for _i in 3..10 { + let c_cell = chip.assign_row(layouter.namespace(|| "next row"), &prev_b, &prev_c)?; + prev_b = prev_c; + prev_c = c_cell; + } + + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 2)?; + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/fibonacci/grouped.rs b/support/zcash-test-circuits/src/fibonacci/grouped.rs new file mode 100644 index 0000000..45c4af9 --- /dev/null +++ b/support/zcash-test-circuits/src/fibonacci/grouped.rs @@ -0,0 +1,133 @@ +use ff::Field; +use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner}; +use halo2_proofs::default_group_key; +use halo2_proofs::plonk::{Circuit, ConstraintSystem, Error}; +use std::marker::PhantomData; + +use crate::fibonacci::{FibonacciConfig, fibonacci_gates}; + +#[derive(Debug, Clone)] +struct FibonacciChip { + config: FibonacciConfig, + _marker: PhantomData, +} + +type FibNums = (AssignedCell, AssignedCell); + +impl FibonacciChip { + pub fn construct(config: FibonacciConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> FibonacciConfig { + fibonacci_gates(meta) + } + + #[allow(clippy::type_complexity)] + pub fn assign_inputs(&self, layouter: &mut impl Layouter) -> Result, Error> { + layouter.assign_region( + || "assign inputs", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + + let a_cell = region.assign_advice_from_instance( + || "f(0)", + self.config.instance, + 0, + self.config.col_a, + 0, + )?; + + let b_cell = region.assign_advice_from_instance( + || "f(1)", + self.config.instance, + 1, + self.config.col_b, + 0, + )?; + + Ok((a_cell, b_cell)) + }, + ) + } + + pub fn step( + &self, + layouter: &mut impl Layouter, + (fib0, fib1): &FibNums, + ) -> Result, Error> { + layouter.group( + || "fib", + default_group_key!(), + |layouter, group| { + group.annotate_inputs([fib0.cell(), fib1.cell()])?; + layouter.assign_region( + || "fib", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + fib0.copy_advice(|| "fib0", &mut region, self.config.col_a, 0)?; + fib1.copy_advice(|| "fib1", &mut region, self.config.col_b, 0)?; + + let fib2 = region.assign_advice( + || "fib2", + self.config.col_c, + 0, + || fib0.value().copied() + fib1.value(), + )?; + + group.annotate_outputs([fib1.cell(), fib2.cell()])?; + Ok((fib1.clone(), fib2)) + }, + ) + }, + ) + } + + pub fn expose_outputs( + &self, + layouter: &mut impl Layouter, + cells: &[AssignedCell], + row: usize, + ) -> Result<(), Error> { + for (n, cell) in cells.iter().enumerate() { + layouter.constrain_instance(cell.cell(), self.config.instance, row + n)?; + } + Ok(()) + } +} + +#[derive(Default)] +pub struct FibonacciCircuit(pub PhantomData); + +impl Circuit for FibonacciCircuit { + type Config = FibonacciConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + FibonacciChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = FibonacciChip::construct(config); + + let mut fib = chip.assign_inputs(&mut layouter)?; + + for _ in 0..7 { + fib = chip.step(&mut layouter, &fib)?; + } + + chip.expose_outputs(&mut layouter, &[fib.0, fib.1], 2)?; + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/lib.rs b/support/zcash-test-circuits/src/lib.rs new file mode 100644 index 0000000..3f37de0 --- /dev/null +++ b/support/zcash-test-circuits/src/lib.rs @@ -0,0 +1,5 @@ +//! Collection of circuits used for testing the Halo2 frontend. + +pub mod fibonacci; +pub mod lookup; +pub mod mul; diff --git a/support/zcash-test-circuits/src/lookup.rs b/support/zcash-test-circuits/src/lookup.rs new file mode 100644 index 0000000..0e73fcf --- /dev/null +++ b/support/zcash-test-circuits/src/lookup.rs @@ -0,0 +1,190 @@ +use ff::Field; +use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}; +use halo2_proofs::plonk::{ + Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance, Selector, TableColumn, +}; +use halo2_proofs::poly::Rotation; +use std::marker::PhantomData; + +pub mod two_by_three; +pub mod two_by_three_fixed; +pub mod two_by_three_zerosel; + +#[derive(Debug, Clone)] +pub struct LookupConfig { + #[allow(dead_code)] + pub col_fixed: Column, + pub lookup_column: TableColumn, + pub col_f: Column, + pub col_a: Column, + pub col_b: Column, + pub col_c: Column, + pub selector: Selector, + pub instance: Column, +} + +#[derive(Debug, Clone)] +struct LookupChip { + config: LookupConfig, + _marker: PhantomData, +} + +impl LookupChip { + pub fn construct(config: LookupConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> LookupConfig { + let col_fixed = meta.fixed_column(); + let col_a = meta.advice_column(); + let col_f = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.complex_selector(); + let instance = meta.instance_column(); + + meta.enable_constant(col_fixed); + meta.enable_equality(col_a); + meta.enable_equality(col_f); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + let lookup_column = meta.lookup_table_column(); + + meta.lookup(|meta| { + let s = meta.query_selector(selector); + let f = meta.query_advice(col_f, Rotation::cur()); + + vec![(s * f, lookup_column)] + }); + + // computes c = -a^2 + meta.create_gate("mul", |meta| { + // + // col_f | col_a | col_b | col_c | selector + // f a b c s + // + let f = meta.query_advice(col_f, Rotation::cur()); + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + halo2_proofs::plonk::Constraints::with_selector( + halo2_proofs::plonk::Expression::Selector(selector), + vec![f * a.clone() - b.clone(), a * b - c], + ) + }); + + LookupConfig { + col_fixed, + lookup_column, + col_a, + col_f, + col_b, + col_c, + selector, + instance, + } + } + + #[allow(clippy::type_complexity)] + pub fn assign_table(&self, mut layouter: impl Layouter) -> Result<(), Error> { + layouter.assign_table( + || "table", + |mut table| { + table.assign_cell( + || "lookup col", + self.config.lookup_column, + 0, + || -> Value { Value::known(-F::ONE) }, + ) + }, + ) + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + mut layouter: impl Layouter, + ) -> Result, Error> { + layouter.assign_region( + || "first row", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + + let fixed_cell = region.assign_advice( + || "-1", + self.config.col_f, + 0, + || -> Value { Value::known(-F::ONE) }, + )?; + + let a_cell = region.assign_advice_from_instance( + || "a", + self.config.instance, + 0, + self.config.col_a, + 0, + )?; + + let b_cell = region.assign_advice( + || "-1 * a", + self.config.col_b, + 0, + || a_cell.value().copied() * fixed_cell.value(), + )?; + + let c_cell = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a_cell.value().copied() * b_cell.value(), + )?; + + Ok(c_cell) + }, + ) + } + + pub fn expose_public( + &self, + mut layouter: impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } +} + +#[derive(Default)] +pub struct LookupCircuit(pub PhantomData); + +impl Circuit for LookupCircuit { + type Config = LookupConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + LookupChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = LookupChip::construct(config); + chip.assign_table(layouter.namespace(|| "table"))?; + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 1)?; + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/lookup/two_by_three.rs b/support/zcash-test-circuits/src/lookup/two_by_three.rs new file mode 100644 index 0000000..b00cb6a --- /dev/null +++ b/support/zcash-test-circuits/src/lookup/two_by_three.rs @@ -0,0 +1,185 @@ +use ff::{Field, PrimeField}; +use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}; +use halo2_proofs::plonk::{ + Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance, Selector, TableColumn, +}; +use halo2_proofs::poly::Rotation; +use std::marker::PhantomData; + +#[derive(Debug, Clone)] +pub struct Lookup2x3Config { + #[allow(dead_code)] + pub col_fixed: Column, + pub lookup_column: [TableColumn; 2], + pub col_f: Column, + pub col_a: Column, + pub col_b: Column, + pub col_c: Column, + pub selector: Selector, + pub instance: Column, +} + +#[derive(Debug, Clone)] +struct Lookup2x3Chip { + config: Lookup2x3Config, + _marker: PhantomData, +} + +impl Lookup2x3Chip { + pub fn construct(config: Lookup2x3Config) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> Lookup2x3Config { + let col_fixed = meta.fixed_column(); + let col_a = meta.advice_column(); + let col_f = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.complex_selector(); + let instance = meta.instance_column(); + + meta.enable_constant(col_fixed); + meta.enable_equality(col_a); + meta.enable_equality(col_f); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + let lookup_column = [meta.lookup_table_column(), meta.lookup_table_column()]; + + meta.lookup(|meta| { + let s = meta.query_selector(selector); + let f = meta.query_advice(col_f, Rotation::cur()); + let a = meta.query_advice(col_a, Rotation::cur()); + + vec![(s.clone() * f, lookup_column[0]), (s * a, lookup_column[1])] + }); + + Lookup2x3Config { + col_fixed, + lookup_column, + col_a, + col_f, + col_b, + col_c, + selector, + instance, + } + } + + fn f(&self, n: usize) -> Value { + Value::known(F::from_u128(n as u128)) + } + + #[allow(clippy::type_complexity)] + pub fn assign_table(&self, mut layouter: impl Layouter) -> Result<(), Error> { + layouter.assign_table( + || "table", + |mut table| { + let fst = [10, 20, 30]; + let snd = [7, 11, 13]; + + fst.into_iter() + .zip(snd.into_iter()) + .enumerate() + .flat_map(|(offset, (x, y))| [(offset, x), (offset, y)]) + .map(|(offset, n)| (offset, self.f(n))) + .zip(self.config.lookup_column.iter().cycle()) + .try_for_each(|((offset, v), t)| { + table.assign_cell( + || format!("lookup col {t:?}"), + *t, + offset, + || -> Value { v }, + ) + }) + }, + ) + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + mut layouter: impl Layouter, + ) -> Result, Error> { + layouter.assign_region( + || "first row", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + + let fixed_cell = region.assign_advice( + || "-1", + self.config.col_f, + 0, + || -> Value { Value::known(-F::ONE) }, + )?; + + let a_cell = region.assign_advice_from_instance( + || "a", + self.config.instance, + 0, + self.config.col_a, + 0, + )?; + + let b_cell = region.assign_advice( + || "-1 * a", + self.config.col_b, + 0, + || a_cell.value().copied() * fixed_cell.value(), + )?; + + let c_cell = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a_cell.value().copied() * b_cell.value(), + )?; + + Ok(c_cell) + }, + ) + } + + pub fn expose_public( + &self, + mut layouter: impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } +} + +#[derive(Default)] +pub struct Lookup2x3Circuit(pub PhantomData); + +impl Circuit for Lookup2x3Circuit { + type Config = Lookup2x3Config; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + Lookup2x3Chip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = Lookup2x3Chip::construct(config); + chip.assign_table(layouter.namespace(|| "table"))?; + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 1)?; + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/lookup/two_by_three_fixed.rs b/support/zcash-test-circuits/src/lookup/two_by_three_fixed.rs new file mode 100644 index 0000000..0cbce86 --- /dev/null +++ b/support/zcash-test-circuits/src/lookup/two_by_three_fixed.rs @@ -0,0 +1,185 @@ +use ff::{Field, PrimeField}; +use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}; +use halo2_proofs::plonk::{ + Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance, Selector, TableColumn, +}; +use halo2_proofs::poly::Rotation; +use std::marker::PhantomData; + +#[derive(Debug, Clone)] +pub struct Lookup2x3Config { + #[allow(dead_code)] + pub col_fixed: Column, + pub lookup_column: [TableColumn; 2], + pub col_f: Column, + pub col_a: Column, + pub col_b: Column, + pub col_c: Column, + pub selector: Selector, + pub instance: Column, +} + +#[derive(Debug, Clone)] +struct Lookup2x3Chip { + config: Lookup2x3Config, + _marker: PhantomData, +} + +impl Lookup2x3Chip { + pub fn construct(config: Lookup2x3Config) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> Lookup2x3Config { + let col_fixed = meta.fixed_column(); + let col_a = meta.advice_column(); + let col_f = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.complex_selector(); + let instance = meta.instance_column(); + + meta.enable_constant(col_fixed); + meta.enable_equality(col_a); + meta.enable_equality(col_f); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + let lookup_column = [meta.lookup_table_column(), meta.lookup_table_column()]; + + meta.lookup(|meta| { + let s = meta.query_selector(selector); + let f = meta.query_fixed(col_fixed); + let a = meta.query_advice(col_a, Rotation::cur()); + + vec![(s.clone() * f, lookup_column[0]), (s * a, lookup_column[1])] + }); + + Lookup2x3Config { + col_fixed, + lookup_column, + col_a, + col_f, + col_b, + col_c, + selector, + instance, + } + } + + fn f(&self, n: usize) -> Value { + Value::known(F::from_u128(n as u128)) + } + + #[allow(clippy::type_complexity)] + pub fn assign_table(&self, mut layouter: impl Layouter) -> Result<(), Error> { + layouter.assign_table( + || "table", + |mut table| { + let fst = [10, 20, 30]; + let snd = [7, 11, 13]; + + fst.into_iter() + .zip(snd.into_iter()) + .enumerate() + .flat_map(|(offset, (x, y))| [(offset, x), (offset, y)]) + .map(|(offset, n)| (offset, self.f(n))) + .zip(self.config.lookup_column.iter().cycle()) + .try_for_each(|((offset, v), t)| { + table.assign_cell( + || format!("lookup col {t:?}"), + *t, + offset, + || -> Value { v }, + ) + }) + }, + ) + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + mut layouter: impl Layouter, + ) -> Result, Error> { + layouter.assign_region( + || "first row", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + + let fixed_cell = region.assign_fixed( + || "-1", + self.config.col_fixed, + 0, + || -> Value { Value::known(-F::ONE) }, + )?; + + let a_cell = region.assign_advice_from_instance( + || "a", + self.config.instance, + 0, + self.config.col_a, + 0, + )?; + + let b_cell = region.assign_advice( + || "-1 * a", + self.config.col_b, + 0, + || a_cell.value().copied() * fixed_cell.value(), + )?; + + let c_cell = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a_cell.value().copied() * b_cell.value(), + )?; + + Ok(c_cell) + }, + ) + } + + pub fn expose_public( + &self, + mut layouter: impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } +} + +#[derive(Default)] +pub struct Lookup2x3Circuit(pub PhantomData); + +impl Circuit for Lookup2x3Circuit { + type Config = Lookup2x3Config; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + Lookup2x3Chip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = Lookup2x3Chip::construct(config); + chip.assign_table(layouter.namespace(|| "table"))?; + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 1)?; + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/lookup/two_by_three_zerosel.rs b/support/zcash-test-circuits/src/lookup/two_by_three_zerosel.rs new file mode 100644 index 0000000..0120bf5 --- /dev/null +++ b/support/zcash-test-circuits/src/lookup/two_by_three_zerosel.rs @@ -0,0 +1,185 @@ +use ff::{Field, PrimeField}; +use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}; +use halo2_proofs::plonk::{ + Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance, Selector, TableColumn, +}; +use halo2_proofs::poly::Rotation; +use std::marker::PhantomData; + +#[derive(Debug, Clone)] +pub struct Lookup2x3ZeroSelConfig { + #[allow(dead_code)] + pub col_fixed: Column, + pub lookup_column: [TableColumn; 2], + pub col_f: Column, + pub col_a: Column, + pub col_b: Column, + pub col_c: Column, + pub selector: Selector, + pub instance: Column, +} + +#[derive(Debug, Clone)] +struct Lookup2x3ZeroSelChip { + config: Lookup2x3ZeroSelConfig, + _marker: PhantomData, +} + +impl Lookup2x3ZeroSelChip { + pub fn construct(config: Lookup2x3ZeroSelConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> Lookup2x3ZeroSelConfig { + let col_fixed = meta.fixed_column(); + let col_a = meta.advice_column(); + let col_f = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.complex_selector(); + let instance = meta.instance_column(); + + meta.enable_constant(col_fixed); + meta.enable_equality(col_a); + meta.enable_equality(col_f); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + let lookup_column = [meta.lookup_table_column(), meta.lookup_table_column()]; + + meta.lookup(|meta| { + let s = meta.query_selector(selector); + let f = meta.query_advice(col_f, Rotation::cur()); + let a = meta.query_advice(col_a, Rotation::cur()); + + vec![(s.clone() * f, lookup_column[0]), (s * a, lookup_column[1])] + }); + + Lookup2x3ZeroSelConfig { + col_fixed, + lookup_column, + col_a, + col_f, + col_b, + col_c, + selector, + instance, + } + } + + fn f(&self, n: usize) -> Value { + Value::known(F::from_u128(n as u128)) + } + + #[allow(clippy::type_complexity)] + pub fn assign_table(&self, mut layouter: impl Layouter) -> Result<(), Error> { + layouter.assign_table( + || "table", + |mut table| { + let fst = [0, 20, 30]; + let snd = [0, 11, 13]; + + fst.into_iter() + .zip(snd.into_iter()) + .enumerate() + .flat_map(|(offset, (x, y))| [(offset, x), (offset, y)]) + .map(|(offset, n)| (offset, self.f(n))) + .zip(self.config.lookup_column.iter().cycle()) + .try_for_each(|((offset, v), t)| { + table.assign_cell( + || format!("lookup col {t:?}"), + *t, + offset, + || -> Value { v }, + ) + }) + }, + ) + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + mut layouter: impl Layouter, + ) -> Result, Error> { + layouter.assign_region( + || "first row", + |mut region| { + //self.config.selector.enable(&mut region, 0)?; + + let fixed_cell = region.assign_advice( + || "-1", + self.config.col_f, + 0, + || -> Value { Value::known(-F::ONE) }, + )?; + + let a_cell = region.assign_advice_from_instance( + || "a", + self.config.instance, + 0, + self.config.col_a, + 0, + )?; + + let b_cell = region.assign_advice( + || "-1 * a", + self.config.col_b, + 0, + || a_cell.value().copied() * fixed_cell.value(), + )?; + + let c_cell = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a_cell.value().copied() * b_cell.value(), + )?; + + Ok(c_cell) + }, + ) + } + + pub fn expose_public( + &self, + mut layouter: impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } +} + +#[derive(Default)] +pub struct Lookup2x3ZeroSelCircuit(pub PhantomData); + +impl Circuit for Lookup2x3ZeroSelCircuit { + type Config = Lookup2x3ZeroSelConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + Lookup2x3ZeroSelChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = Lookup2x3ZeroSelChip::construct(config); + chip.assign_table(layouter.namespace(|| "table"))?; + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 1)?; + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/mul.rs b/support/zcash-test-circuits/src/mul.rs new file mode 100644 index 0000000..a6edfa2 --- /dev/null +++ b/support/zcash-test-circuits/src/mul.rs @@ -0,0 +1,162 @@ +use ff::Field; +use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}; +use halo2_proofs::plonk::{ + Advice, Circuit, Column, ConstraintSystem, Error, Expression, Fixed, Instance, Selector, +}; +use halo2_proofs::poly::Rotation; +use std::marker::PhantomData; + +pub mod fixed_constraint; +pub mod flipped_constraint; +pub mod grouped; +pub mod injection; +pub mod recursive_groups; +pub mod ten_plus_io; + +#[derive(Debug, Clone)] +pub struct MulConfig { + pub col_fixed: Column, + pub col_a: Column, + pub col_b: Column, + pub col_c: Column, + pub selector: Selector, + pub instance: Column, +} + +#[derive(Debug, Clone)] +struct MulChip { + config: MulConfig, + _marker: PhantomData, +} + +impl MulChip { + pub fn construct(config: MulConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> MulConfig { + let col_fixed = meta.fixed_column(); + let col_a = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.selector(); + let instance = meta.instance_column(); + + meta.enable_constant(col_fixed); + meta.enable_equality(col_a); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + // computes c = -a^2 + meta.create_gate("mul", |meta| { + // + // col_fixed | col_a | col_b | col_c | selector + // f a b c s + // + let f = meta.query_fixed(col_fixed); + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + halo2_proofs::plonk::Constraints::with_selector( + Expression::Selector(selector), + vec![f * a.clone() - b.clone(), a * b - c], + ) + }); + + MulConfig { + col_fixed, + col_a, + col_b, + col_c, + selector, + instance, + } + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + mut layouter: impl Layouter, + ) -> Result, Error> { + layouter.assign_region( + || "first row", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + + let fixed_cell = region.assign_fixed( + || "-1", + self.config.col_fixed, + 0, + || -> Value { Value::known(-F::ONE) }, + )?; + + let a_cell = region.assign_advice_from_instance( + || "a", + self.config.instance, + 0, + self.config.col_a, + 0, + )?; + + let b_cell = region.assign_advice( + || "-1 * a", + self.config.col_b, + 0, + || a_cell.value().copied() * fixed_cell.value(), + )?; + + let c_cell = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a_cell.value().copied() * b_cell.value(), + )?; + + Ok(c_cell) + }, + ) + } + + pub fn expose_public( + &self, + mut layouter: impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } +} + +#[derive(Default)] +pub struct MulCircuit(pub PhantomData); + +impl Circuit for MulCircuit { + type Config = MulConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + MulChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = MulChip::construct(config); + + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 1)?; + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/mul/fixed_constraint.rs b/support/zcash-test-circuits/src/mul/fixed_constraint.rs new file mode 100644 index 0000000..b2ea060 --- /dev/null +++ b/support/zcash-test-circuits/src/mul/fixed_constraint.rs @@ -0,0 +1,179 @@ +use ff::Field; +use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}; +use halo2_proofs::plonk::{ + Advice, Circuit, Column, ConstraintSystem, Error, Expression, Fixed, Instance, Selector, +}; +use halo2_proofs::poly::Rotation; +use std::marker::PhantomData; + +#[derive(Debug, Clone)] +pub struct MulWithFixedConstraintConfig { + pub col_fixed: Column, + pub col_fixed2: Column, + pub col_a: Column, + pub col_b: Column, + pub col_c: Column, + pub col_d: Column, + pub selector: Selector, + pub instance: Column, +} + +#[derive(Debug, Clone)] +struct MulChip { + config: MulWithFixedConstraintConfig, + _marker: PhantomData, +} + +impl MulChip { + pub fn construct(config: MulWithFixedConstraintConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> MulWithFixedConstraintConfig { + let col_fixed = meta.fixed_column(); + let col_fixed2 = meta.fixed_column(); + let col_a = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let col_d = meta.advice_column(); + let selector = meta.selector(); + let instance = meta.instance_column(); + + meta.enable_constant(col_fixed2); + meta.enable_equality(col_a); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(col_d); + meta.enable_equality(instance); + + // computes c = -a^2 + meta.create_gate("mul", |meta| { + // + // col_fixed | col_a | col_b | col_c | selector + // f a b c s + // + let f = meta.query_fixed(col_fixed); + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + halo2_proofs::plonk::Constraints::with_selector( + Expression::Selector(selector), + vec![f * a.clone() - b.clone(), a * b - c], + ) + }); + + meta.create_gate("equal -1", |meta| { + let f = meta.query_fixed(col_fixed); + let f2 = meta.query_fixed(col_fixed2); + + halo2_proofs::plonk::Constraints::with_selector( + Expression::Selector(selector), + vec![(f - f2) + Expression::Constant(F::ONE + F::ONE + F::ONE)], + ) + }); + + MulWithFixedConstraintConfig { + col_fixed, + col_fixed2, + col_a, + col_b, + col_c, + col_d, + selector, + instance, + } + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + mut layouter: impl Layouter, + ) -> Result, Error> { + layouter.assign_region( + || "first row", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + + let fixed_cell = region.assign_fixed( + || "-1", + self.config.col_fixed, + 0, + || -> Value { Value::known(-F::ONE) }, + )?; + + let a_cell = region.assign_advice_from_instance( + || "a", + self.config.instance, + 0, + self.config.col_a, + 0, + )?; + + let b_cell = region.assign_advice( + || "-1 * a", + self.config.col_b, + 0, + || a_cell.value().copied() * fixed_cell.value(), + )?; + + let c_cell = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a_cell.value().copied() * b_cell.value(), + )?; + + region.assign_advice_from_constant( + || "const", + self.config.col_d, + 0, + F::ONE + F::ONE, + )?; + + Ok(c_cell) + }, + ) + } + + pub fn expose_public( + &self, + mut layouter: impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } +} + +#[derive(Default)] +pub struct MulWithFixedConstraintCircuit(pub PhantomData); + +impl Circuit for MulWithFixedConstraintCircuit { + type Config = MulWithFixedConstraintConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + MulChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = MulChip::construct(config); + + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 1)?; + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/mul/flipped_constraint.rs b/support/zcash-test-circuits/src/mul/flipped_constraint.rs new file mode 100644 index 0000000..363f576 --- /dev/null +++ b/support/zcash-test-circuits/src/mul/flipped_constraint.rs @@ -0,0 +1,145 @@ +use ff::Field; +use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}; +use halo2_proofs::plonk::{Circuit, ConstraintSystem, Error, Expression}; +use halo2_proofs::poly::Rotation; +use std::marker::PhantomData; + +use crate::mul::MulConfig; + +#[derive(Debug, Clone)] +struct MulChip { + config: MulConfig, + _marker: PhantomData, +} + +impl MulChip { + pub fn construct(config: MulConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> MulConfig { + let col_fixed = meta.fixed_column(); + let col_a = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.selector(); + let instance = meta.instance_column(); + + meta.enable_constant(col_fixed); + meta.enable_equality(col_a); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + // computes c = -a^2 + meta.create_gate("mul", |meta| { + // + // col_fixed | col_a | col_b | col_c | selector + // f a b c s + // + let f = meta.query_fixed(col_fixed); + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + halo2_proofs::plonk::Constraints::with_selector( + Expression::Selector(selector), + vec![f * a.clone() - b.clone(), -c + (a * b)], + ) + }); + + MulConfig { + col_fixed, + col_a, + col_b, + col_c, + selector, + instance, + } + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + mut layouter: impl Layouter, + ) -> Result, Error> { + layouter.assign_region( + || "first row", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + + let fixed_cell = region.assign_fixed( + || "-1", + self.config.col_fixed, + 0, + || -> Value { Value::known(-F::ONE) }, + )?; + + let a_cell = region.assign_advice_from_instance( + || "a", + self.config.instance, + 0, + self.config.col_a, + 0, + )?; + + let b_cell = region.assign_advice( + || "-1 * a", + self.config.col_b, + 0, + || a_cell.value().copied() * fixed_cell.value(), + )?; + + let c_cell = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a_cell.value().copied() * b_cell.value(), + )?; + + Ok(c_cell) + }, + ) + } + + pub fn expose_public( + &self, + mut layouter: impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } +} + +#[derive(Default)] +pub struct MulCircuit(pub PhantomData); + +impl Circuit for MulCircuit { + type Config = MulConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + MulChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = MulChip::construct(config); + + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 1)?; + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/mul/grouped.rs b/support/zcash-test-circuits/src/mul/grouped.rs new file mode 100644 index 0000000..db9e11e --- /dev/null +++ b/support/zcash-test-circuits/src/mul/grouped.rs @@ -0,0 +1,49 @@ +use super::MulChip; +use crate::mul::MulConfig; +use ff::Field; +use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner}, + default_group_key, + plonk::{Circuit, ConstraintSystem, Error}, +}; +use std::marker::PhantomData; + +pub mod deep_callstack; +pub mod different_bodies; +pub mod same_body; + +#[derive(Default)] +pub struct MulCircuit(pub PhantomData); + +impl Circuit for MulCircuit { + type Config = MulConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + MulChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = MulChip::construct(config); + let prev_c = layouter.group( + || "test group", + default_group_key!(), + |layouter, group| { + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + group.annotate_output(prev_c.cell())?; + Ok(prev_c) + }, + )?; + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 1)?; + + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/mul/grouped/deep_callstack.rs b/support/zcash-test-circuits/src/mul/grouped/deep_callstack.rs new file mode 100644 index 0000000..d1317a4 --- /dev/null +++ b/support/zcash-test-circuits/src/mul/grouped/deep_callstack.rs @@ -0,0 +1,284 @@ +use ff::Field; +use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}; +use halo2_proofs::default_group_key; +use halo2_proofs::plonk::{ + Advice, Circuit, Column, ConstraintSystem, Constraints, Error, Expression, Fixed, Instance, + Selector, +}; +use halo2_proofs::poly::Rotation; +use std::marker::PhantomData; + +#[derive(Debug, Clone)] +pub struct MulConfig { + pub col_fixed: Column, + pub col_a: Column, + pub col_b: Column, + pub col_c: Column, + pub selector: Selector, + pub selector2: Selector, + pub selector3: Selector, + pub instance: Column, +} + +#[derive(Debug, Clone)] +struct MulChip { + config: MulConfig, + _marker: PhantomData, +} + +impl MulChip { + pub fn construct(config: MulConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> MulConfig { + let col_fixed = meta.fixed_column(); + let col_a = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.selector(); + let selector2 = meta.selector(); + let selector3 = meta.selector(); + let instance = meta.instance_column(); + + meta.enable_constant(col_fixed); + meta.enable_equality(col_a); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + // computes c = -a^2 + meta.create_gate("mul", |meta| { + // + // col_fixed | col_a | col_b | col_c | selector + // f a b c s + // + let f = meta.query_fixed(col_fixed); + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + Constraints::with_selector( + Expression::Selector(selector), + vec![f * a.clone() - b.clone(), a * b - c], + ) + }); + + // computes c = -a^2 + meta.create_gate("mul2", |meta| { + // + // col_fixed | col_a | col_b | col_c | selector + // f a b c s + // + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + Constraints::with_selector(Expression::Selector(selector2), vec![a * b - c]) + }); + + // computes c = -a^2 + meta.create_gate("mul3", |meta| { + // + // col_fixed | col_a | col_b | col_c | selector + // f a b c s + // + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + Constraints::with_selector(Expression::Selector(selector3), vec![a * b - c]) + }); + + MulConfig { + col_fixed, + col_a, + col_b, + col_c, + selector, + selector2, + selector3, + instance, + } + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + layouter: &mut impl Layouter, + input: &AssignedCell, + selector: Selector, + ) -> Result, Error> { + layouter.assign_region( + || "first row", + |mut region| { + selector.enable(&mut region, 0)?; + + let fixed_cell = region.assign_fixed( + || "-1", + self.config.col_fixed, + 0, + || -> Value { Value::known(-F::ONE) }, + )?; + + let a_cell = region.assign_advice( + || "a", + self.config.col_a, + 0, + || input.value().copied(), + )?; + region.constrain_equal(input.cell(), a_cell.cell())?; + + let b_cell = region.assign_advice( + || "-1 * a", + self.config.col_b, + 0, + || a_cell.value().copied() * fixed_cell.value(), + )?; + + let c_cell = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a_cell.value().copied() * b_cell.value(), + )?; + + Ok(c_cell) + }, + ) + } + + pub fn expose_public( + &self, + layouter: &mut impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } + + pub fn assign_a(&self, layouter: &mut impl Layouter) -> Result, Error> { + layouter.assign_region( + || "set a", + |mut region| { + region.assign_advice_from_instance( + || "a", + self.config.instance, + 0, + self.config.col_a, + 0, + ) + }, + ) + } + + pub fn assign_c( + &self, + layouter: &mut impl Layouter, + cell: &AssignedCell, + ) -> Result, Error> { + layouter.assign_region( + || "set c", + |mut region| { + let c = + region.assign_advice(|| "c", self.config.col_c, 0, || cell.value().copied())?; + region.constrain_equal(cell.cell(), c.cell())?; + Ok(c) + }, + ) + } + + pub fn inner_group( + &self, + layouter: &mut impl Layouter, + input: &AssignedCell, + selector: Selector, + ) -> Result, Error> { + layouter.group( + || "inner group", + default_group_key!(), + |layouter, group| { + group.annotate_input(input.cell())?; + let prev_c = self.assign_first_row(layouter, input, selector)?; + group.annotate_output(prev_c.cell())?; + Ok(prev_c) + }, + ) + } + + pub fn outer_group( + &self, + layouter: &mut impl Layouter, + input: &AssignedCell, + selector: Selector, + selector3: Selector, + ) -> Result, Error> { + layouter.group( + || "outer group", + default_group_key!(), + |layouter, group| { + group.annotate_input(input.cell())?; + let c = self.inner_group(layouter, input, selector3)?; + let c = self.assign_first_row(layouter, &c, selector)?; + group.annotate_output(c.cell())?; + Ok(c) + }, + ) + } + + /// This group is dynamic and will enable a different set of gates depending on the group. + pub fn call_group( + &self, + layouter: &mut impl Layouter, + input: &AssignedCell, + selector: Selector, + ) -> Result, Error> { + layouter.group( + || "test group", + // Defined here to get always the same key. + default_group_key!(), + |layouter, group| { + group.annotate_input(input.cell())?; + let prev_c = self.assign_first_row(layouter, input, selector)?; + group.annotate_output(prev_c.cell())?; + Ok(prev_c) + }, + ) + } +} + +#[derive(Default)] +pub struct MulCircuit(pub PhantomData); + +impl Circuit for MulCircuit { + type Config = MulConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + MulChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = MulChip::construct(config.clone()); + let a = chip.assign_a(&mut layouter)?; + let c = chip.call_group(&mut layouter, &a, config.selector)?; + let c = chip.call_group(&mut layouter, &c, config.selector)?; + let c = chip.call_group(&mut layouter, &c, config.selector2)?; + let c = chip.outer_group(&mut layouter, &c, config.selector, config.selector3)?; + let pub_c = chip.assign_c(&mut layouter, &c)?; + chip.expose_public(&mut layouter, &pub_c, 1)?; + + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/mul/grouped/different_bodies.rs b/support/zcash-test-circuits/src/mul/grouped/different_bodies.rs new file mode 100644 index 0000000..c198688 --- /dev/null +++ b/support/zcash-test-circuits/src/mul/grouped/different_bodies.rs @@ -0,0 +1,229 @@ +use ff::Field; +use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}; +use halo2_proofs::default_group_key; +use halo2_proofs::plonk::{ + Advice, Circuit, Column, ConstraintSystem, Constraints, Error, Expression, Fixed, Instance, + Selector, +}; +use halo2_proofs::poly::Rotation; +use std::marker::PhantomData; + +#[derive(Debug, Clone)] +pub struct MulConfig { + pub col_fixed: Column, + pub col_a: Column, + pub col_b: Column, + pub col_c: Column, + pub selector: Selector, + pub selector2: Selector, + pub instance: Column, +} + +#[derive(Debug, Clone)] +struct MulChip { + config: MulConfig, + _marker: PhantomData, +} + +impl MulChip { + pub fn construct(config: MulConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> MulConfig { + let col_fixed = meta.fixed_column(); + let col_a = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.selector(); + let selector2 = meta.selector(); + let instance = meta.instance_column(); + + meta.enable_constant(col_fixed); + meta.enable_equality(col_a); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + // computes c = -a^2 + meta.create_gate("mul", |meta| { + // + // col_fixed | col_a | col_b | col_c | selector + // f a b c s + // + let f = meta.query_fixed(col_fixed); + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + Constraints::with_selector( + Expression::Selector(selector), + vec![f * a.clone() - b.clone(), a * b - c], + ) + }); + + // computes c = -a^2 + meta.create_gate("mul2", |meta| { + // + // col_fixed | col_a | col_b | col_c | selector + // f a b c s + // + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + Constraints::with_selector(Expression::Selector(selector2), vec![a * b - c]) + }); + + MulConfig { + col_fixed, + col_a, + col_b, + col_c, + selector, + selector2, + instance, + } + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + layouter: &mut impl Layouter, + input: &AssignedCell, + selector: Selector, + ) -> Result, Error> { + layouter.assign_region( + || "first row", + |mut region| { + selector.enable(&mut region, 0)?; + + let fixed_cell = region.assign_fixed( + || "-1", + self.config.col_fixed, + 0, + || -> Value { Value::known(-F::ONE) }, + )?; + + let a_cell = region.assign_advice( + || "a", + self.config.col_a, + 0, + || input.value().copied(), + )?; + region.constrain_equal(input.cell(), a_cell.cell())?; + + let b_cell = region.assign_advice( + || "-1 * a", + self.config.col_b, + 0, + || a_cell.value().copied() * fixed_cell.value(), + )?; + + let c_cell = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a_cell.value().copied() * b_cell.value(), + )?; + + Ok(c_cell) + }, + ) + } + + pub fn expose_public( + &self, + layouter: &mut impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } + + pub fn assign_a(&self, layouter: &mut impl Layouter) -> Result, Error> { + layouter.assign_region( + || "set a", + |mut region| { + region.assign_advice_from_instance( + || "a", + self.config.instance, + 0, + self.config.col_a, + 0, + ) + }, + ) + } + + pub fn assign_c( + &self, + layouter: &mut impl Layouter, + cell: &AssignedCell, + ) -> Result, Error> { + layouter.assign_region( + || "set c", + |mut region| { + let c = + region.assign_advice(|| "c", self.config.col_c, 0, || cell.value().copied())?; + region.constrain_equal(cell.cell(), c.cell())?; + Ok(c) + }, + ) + } + + /// This group is dynamic and will enable a different set of gates depending on the group. + pub fn call_group( + &self, + layouter: &mut impl Layouter, + input: &AssignedCell, + selector: Selector, + ) -> Result, Error> { + layouter.group( + || "test group", + // Defined here to get always the same key. + default_group_key!(), + |layouter, group| { + group.annotate_input(input.cell())?; + let prev_c = self.assign_first_row(layouter, input, selector)?; + group.annotate_output(prev_c.cell())?; + Ok(prev_c) + }, + ) + } +} + +#[derive(Default)] +pub struct MulCircuit(pub PhantomData); + +impl Circuit for MulCircuit { + type Config = MulConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + MulChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = MulChip::construct(config.clone()); + let a = chip.assign_a(&mut layouter)?; + let c = chip.call_group(&mut layouter, &a, config.selector)?; + let c = chip.call_group(&mut layouter, &c, config.selector)?; + let c = chip.call_group(&mut layouter, &c, config.selector2)?; + let pub_c = chip.assign_c(&mut layouter, &c)?; + chip.expose_public(&mut layouter, &pub_c, 1)?; + + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/mul/grouped/same_body.rs b/support/zcash-test-circuits/src/mul/grouped/same_body.rs new file mode 100644 index 0000000..e0ea626 --- /dev/null +++ b/support/zcash-test-circuits/src/mul/grouped/same_body.rs @@ -0,0 +1,200 @@ +use ff::Field; +use halo2_proofs::{ + circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}, + default_group_key, + plonk::{Circuit, ConstraintSystem, Error, Expression}, + poly::Rotation, +}; +use std::marker::PhantomData; + +use crate::mul::MulConfig; + +#[derive(Debug, Clone)] +struct MulChip { + config: MulConfig, + _marker: PhantomData, +} + +impl MulChip { + pub fn construct(config: MulConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> MulConfig { + let col_fixed = meta.fixed_column(); + let col_a = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.selector(); + let instance = meta.instance_column(); + + meta.enable_constant(col_fixed); + meta.enable_equality(col_a); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + // computes c = -a^2 + meta.create_gate("mul", |meta| { + // + // col_fixed | col_a | col_b | col_c | selector + // f a b c s + // + let f = meta.query_fixed(col_fixed); + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + halo2_proofs::plonk::Constraints::with_selector( + Expression::Selector(selector), + vec![f * a.clone() - b.clone(), a * b - c], + ) + }); + + MulConfig { + col_fixed, + col_a, + col_b, + col_c, + selector, + instance, + } + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + layouter: &mut impl Layouter, + input: &AssignedCell, + ) -> Result, Error> { + layouter.assign_region( + || "first row", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + + let fixed_cell = region.assign_fixed( + || "-1", + self.config.col_fixed, + 0, + || -> Value { Value::known(-F::ONE) }, + )?; + + let a_cell = region.assign_advice( + || "a", + self.config.col_a, + 0, + || input.value().copied(), + )?; + region.constrain_equal(input.cell(), a_cell.cell())?; + + let b_cell = region.assign_advice( + || "-1 * a", + self.config.col_b, + 0, + || a_cell.value().copied() * fixed_cell.value(), + )?; + + let c_cell = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a_cell.value().copied() * b_cell.value(), + )?; + + Ok(c_cell) + }, + ) + } + + pub fn assign_a(&self, layouter: &mut impl Layouter) -> Result, Error> { + layouter.assign_region( + || "set a", + |mut region| { + region.assign_advice_from_instance( + || "a", + self.config.instance, + 0, + self.config.col_a, + 0, + ) + }, + ) + } + + pub fn assign_c( + &self, + layouter: &mut impl Layouter, + cell: &AssignedCell, + ) -> Result, Error> { + layouter.assign_region( + || "set c", + |mut region| { + let c = + region.assign_advice(|| "c", self.config.col_c, 0, || cell.value().copied())?; + region.constrain_equal(cell.cell(), c.cell())?; + Ok(c) + }, + ) + } + + pub fn expose_public( + &self, + layouter: &mut impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } + + pub fn call_group( + &self, + layouter: &mut impl Layouter, + input: &AssignedCell, + ) -> Result, Error> { + layouter.group( + || "test group", + // Defined here to get always the same key. + default_group_key!(), + |layouter, group| { + group.annotate_input(input.cell())?; + let prev_c = self.assign_first_row(layouter, input)?; + group.annotate_output(prev_c.cell())?; + Ok(prev_c) + }, + ) + } +} + +#[derive(Default)] +pub struct MulCircuit(pub PhantomData); + +impl Circuit for MulCircuit { + type Config = MulConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + MulChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = MulChip::construct(config); + let a = chip.assign_a(&mut layouter)?; + let c = chip.call_group(&mut layouter, &a)?; + let c = chip.call_group(&mut layouter, &c)?; + let pub_c = chip.assign_c(&mut layouter, &c)?; + chip.expose_public(&mut layouter, &pub_c, 1)?; + + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/mul/injection.rs b/support/zcash-test-circuits/src/mul/injection.rs new file mode 100644 index 0000000..ff46c7c --- /dev/null +++ b/support/zcash-test-circuits/src/mul/injection.rs @@ -0,0 +1,148 @@ +use ff::Field; +use halo2_proofs::{ + circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}, + plonk::{Circuit, ConstraintSystem, Error, Expression}, + poly::Rotation, +}; +use std::marker::PhantomData; + +use crate::mul::MulConfig; + +#[derive(Debug, Clone)] +struct MulChip { + config: MulConfig, + _marker: PhantomData, +} + +impl MulChip { + pub fn construct(config: MulConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> MulConfig { + let col_fixed = meta.fixed_column(); + let col_a = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.selector(); + let instance = meta.instance_column(); + + meta.enable_constant(col_fixed); + meta.enable_equality(col_a); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + // computes c = -a^2 + meta.create_gate("mul", |meta| { + // + // col_fixed | col_a | col_b | col_c | selector + // f a b c s + // + let f = meta.query_fixed(col_fixed); + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_a, Rotation::next()); + let c = meta.query_advice(col_c, Rotation::cur()); + + halo2_proofs::plonk::Constraints::with_selector( + Expression::Selector(selector), + vec![f * a.clone() - b.clone(), a * b - c], + ) + }); + + MulConfig { + col_fixed, + col_a, + col_b: meta.advice_column(), + col_c, + selector, + instance, + } + } + + #[allow(clippy::type_complexity)] + pub fn assign_first_row( + &self, + mut layouter: impl Layouter, + ) -> Result, Error> { + layouter.assign_region( + || "first row", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + + let fixed_cell = region.assign_fixed( + || "-1", + self.config.col_fixed, + 0, + || -> Value { Value::known(-F::ONE) }, + )?; + + let a_cell = region.assign_advice_from_instance( + || "a", + self.config.instance, + 0, + self.config.col_a, + 0, + )?; + + let b_cell = region.assign_advice( + || "-1 * a", + self.config.col_a, + 1, + || a_cell.value().copied() * fixed_cell.value(), + )?; + + let c_cell = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a_cell.value().copied() * b_cell.value(), + )?; + + Ok(c_cell) + }, + ) + } + + pub fn expose_public( + &self, + mut layouter: impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } +} + +#[derive(Default)] +pub struct MulCircuit(pub PhantomData); + +impl Circuit for MulCircuit { + type Config = MulConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + MulChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = MulChip::construct(config); + + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 1)?; + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 2)?; + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 3)?; + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/mul/recursive_groups.rs b/support/zcash-test-circuits/src/mul/recursive_groups.rs new file mode 100644 index 0000000..32a3063 --- /dev/null +++ b/support/zcash-test-circuits/src/mul/recursive_groups.rs @@ -0,0 +1,175 @@ +use ff::Field; +use halo2_proofs::plonk::Expression; +use halo2_proofs::poly::Rotation; +use halo2_proofs::{ + circuit::{AssignedCell, Layouter, SimpleFloorPlanner}, + default_group_key, + plonk::{Circuit, ConstraintSystem, Error}, +}; +use std::marker::PhantomData; + +use crate::mul::MulConfig; + +const N_INPUTS: usize = 4; + +#[derive(Debug, Clone)] +struct MulChip { + config: MulConfig, + _marker: PhantomData, +} + +impl MulChip { + pub fn construct(config: MulConfig) -> Self { + Self { + config, + _marker: PhantomData, + } + } + + pub fn configure(meta: &mut ConstraintSystem) -> MulConfig { + let col_a = meta.advice_column(); + let col_b = meta.advice_column(); + let col_c = meta.advice_column(); + let selector = meta.selector(); + let instance = meta.instance_column(); + + meta.enable_equality(col_a); + meta.enable_equality(col_b); + meta.enable_equality(col_c); + meta.enable_equality(instance); + + meta.create_gate("mul", |meta| { + // + // col_fixed | col_a | col_b | col_c | selector + // f a b c s + // + let a = meta.query_advice(col_a, Rotation::cur()); + let b = meta.query_advice(col_b, Rotation::cur()); + let c = meta.query_advice(col_c, Rotation::cur()); + + halo2_proofs::plonk::Constraints::with_selector( + Expression::Selector(selector), + vec![a * b - c], + ) + }); + + MulConfig { + col_fixed: meta.fixed_column(), + col_a, + col_b, + col_c, + selector, + instance, + } + } + + pub fn expose_public( + &self, + layouter: &mut impl Layouter, + cell: &AssignedCell, + row: usize, + ) -> Result<(), Error> { + layouter.constrain_instance(cell.cell(), self.config.instance, row) + } + + pub fn mul_many( + &self, + layouter: &mut impl Layouter, + operands: &[AssignedCell], + ) -> Result, Error> { + if operands.len() == 1 { + return Ok(operands[0].clone()); + } + layouter.group( + || "mul_many", + default_group_key!(), + |layouter, group| { + group.annotate_inputs(operands.iter().map(|op| op.cell()))?; + let lhs = &operands[0]; + let rhs = self.mul_many(layouter, &operands[1..])?; + layouter.assign_region( + || "mul", + |mut region| { + self.config.selector.enable(&mut region, 0)?; + assert!(operands.len() > 1); + + let a = region.assign_advice( + || "a = lhs", + self.config.col_a, + 0, + || lhs.value().copied(), + )?; + region.constrain_equal(lhs.cell(), a.cell())?; + let b = region.assign_advice( + || "b = rhs", + self.config.col_b, + 0, + || rhs.value().copied(), + )?; + region.constrain_equal(rhs.cell(), b.cell())?; + let c = region.assign_advice( + || "a * b", + self.config.col_c, + 0, + || a.value().copied() * b.value(), + )?; + group.annotate_output(c.cell())?; + Ok(c) + }, + ) + }, + ) + } + + pub fn assign_inputs( + &self, + layouter: &mut impl Layouter, + input_count: usize, + ) -> Result>, Error> { + layouter.assign_region( + || "input loading", + |mut region| { + (0..input_count) + .map(|n| { + region.assign_advice_from_instance( + || format!("input {n}"), + self.config.instance, + n, + self.config.col_a, + n, + ) + }) + .collect() + }, + ) + } +} + +#[derive(Default)] +pub struct MulCircuit(pub PhantomData); + +impl Circuit for MulCircuit { + type Config = MulConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + MulChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = MulChip::construct(config); + let inputs = chip.assign_inputs(&mut layouter, N_INPUTS)?; + let output = chip.mul_many(&mut layouter, &inputs)?; + chip.expose_public(&mut layouter, &output, inputs.len())?; + + Ok(()) + } +} diff --git a/support/zcash-test-circuits/src/mul/ten_plus_io.rs b/support/zcash-test-circuits/src/mul/ten_plus_io.rs new file mode 100644 index 0000000..2f22c11 --- /dev/null +++ b/support/zcash-test-circuits/src/mul/ten_plus_io.rs @@ -0,0 +1,37 @@ +use super::MulChip; +use crate::mul::MulConfig; +use ff::Field; +use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner}, + plonk::{Circuit, ConstraintSystem, Error}, +}; +use std::marker::PhantomData; + +#[derive(Default)] +pub struct MulCircuit(pub PhantomData); + +impl Circuit for MulCircuit { + type Config = MulConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + MulChip::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = MulChip::construct(config); + + let prev_c = chip.assign_first_row(layouter.namespace(|| "first row"))?; + + chip.expose_public(layouter.namespace(|| "out"), &prev_c, 11)?; + Ok(()) + } +}