diff --git a/.devcontainer/scripts/onCreateCommand.sh b/.devcontainer/scripts/onCreateCommand.sh index f90491c9bd0..e9c1b90f765 100755 --- a/.devcontainer/scripts/onCreateCommand.sh +++ b/.devcontainer/scripts/onCreateCommand.sh @@ -17,10 +17,10 @@ corepack enable if [ "$TYPE" != "sandbox_only" ]; then source ~/.bashrc - yes | npx create-aztec-app -t $TYPE -n $NAME -s + yes | npx aztec-app -t $TYPE -n $NAME -s mv $NAME/* $NAME/.* . rm -rf $NAME - + yarn npx -y playwright install --with-deps diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f3420cf23b2..78bab204d48 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,11 @@ on: push: branches: [master, provernet] pull_request: + types: + - opened + - reopened + - synchronize + - ready_for_review branches-ignore: [devnet] workflow_dispatch: inputs: {} @@ -28,6 +33,7 @@ env: jobs: setup: + if: github.event.pull_request.draft == false uses: ./.github/workflows/setup-runner.yml with: username: ${{ github.event.pull_request.user.login || github.actor }} @@ -36,6 +42,7 @@ jobs: changes: runs-on: ubuntu-20.04 + if: github.event.pull_request.draft == false # Required permissions. permissions: pull-requests: read @@ -92,21 +99,21 @@ jobs: runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 steps: - uses: actions/checkout@v4 - if: ${{ needs.changes.outputs.build-images == 'true' }} + if: needs.changes.outputs.build-images == 'true' with: { ref: "${{ env.GIT_COMMIT }}" } - uses: ./.github/ci-setup-action - if: ${{ needs.changes.outputs.build-images == 'true' }} + if: needs.changes.outputs.build-images == 'true' with: concurrency_key: build-images-x86 - name: "Push Build Images If Changed" - if: ${{ needs.changes.outputs.build-images == 'true' }} + if: needs.changes.outputs.build-images == 'true' timeout-minutes: 40 run: | earthly-ci --push ./build-images/+build build: needs: [build-images, changes] - if: ${{ needs.changes.outputs.non-docs == 'true' && needs.changes.outputs.non-misc-ci == 'true' && needs.changes.outputs.non-barretenberg-cpp == 'true' }} + if: needs.changes.outputs.non-docs == 'true' && needs.changes.outputs.non-misc-ci == 'true' && needs.changes.outputs.non-barretenberg-cpp == 'true' runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 outputs: e2e_list: ${{ steps.e2e_list.outputs.list }} @@ -134,7 +141,7 @@ jobs: # all the non-bench end-to-end integration tests for aztec e2e: needs: [build, changes] - if: ${{ needs.changes.outputs.non-barretenberg-cpp == 'true' }} + if: needs.changes.outputs.non-barretenberg-cpp == 'true' runs-on: ubuntu-20.04 strategy: fail-fast: false @@ -164,7 +171,7 @@ jobs: # all the benchmarking end-to-end integration tests for aztec (not required to merge) bench-e2e: needs: [build, changes] - if: ${{ needs.changes.outputs.non-barretenberg-cpp == 'true' }} + if: needs.changes.outputs.non-barretenberg-cpp == 'true' runs-on: ubuntu-20.04 strategy: fail-fast: false @@ -197,7 +204,7 @@ jobs: runs-on: ubuntu-20.04 needs: [build-images, changes] # Note: not fully accurate, but to work with bench-summary needs to be the same as bench-e2e - if: ${{ needs.changes.outputs.non-barretenberg-cpp == 'true' }} + if: needs.changes.outputs.non-barretenberg-cpp == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -239,7 +246,7 @@ jobs: run: | earthly-ci -P +bench-aggregate - name: "Download base benchmark and package into earthly" - if: ${{ github.event_name == 'pull_request' }} + if: github.event_name == 'pull_request' run: | # Download the base benchmark locally (requires AWS creds and .git history) mkdir -p $BENCH_FOLDER @@ -252,7 +259,7 @@ jobs: BENCH_FOLDER: "./scripts/logs/tmp/bench" PULL_REQUEST: "${{ github.event.pull_request.number }}" - name: "Generate summary comment if pull request" - if: ${{ github.event_name == 'pull_request' }} + if: github.event_name == 'pull_request' working-directory: ./yarn-project/scripts run: | earthly-ci -P +bench-comment @@ -262,7 +269,7 @@ jobs: bb-gcc: needs: [build-images, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.barretenberg-cpp == 'true' }} + if: needs.changes.outputs.barretenberg-cpp == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -282,7 +289,7 @@ jobs: bb-native-tests: needs: [build-images, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.barretenberg-cpp == 'true' }} + if: needs.changes.outputs.barretenberg-cpp == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -300,7 +307,7 @@ jobs: bb-js-test: needs: [build-images, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.barretenberg == 'true' }} + if: needs.changes.outputs.barretenberg == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -315,7 +322,7 @@ jobs: noir-build-acir-tests: needs: [build-images, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' }} + if: needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -329,7 +336,7 @@ jobs: bb-acir-tests-bb: needs: [noir-build-acir-tests, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' }} + if: needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -344,7 +351,7 @@ jobs: bb-acir-tests-sol: needs: [noir-build-acir-tests, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' }} + if: needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -359,7 +366,7 @@ jobs: bb-acir-tests-sol-honk: needs: [noir-build-acir-tests, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' }} + if: needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -374,7 +381,7 @@ jobs: bb-acir-tests-bb-js: needs: [noir-build-acir-tests, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' }} + if: needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -389,7 +396,7 @@ jobs: noir-format: needs: [build-images, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.noir == 'true' || needs.changes.outputs.noir-projects == 'true' }} + if: needs.changes.outputs.noir == 'true' || needs.changes.outputs.noir-projects == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -409,7 +416,7 @@ jobs: noir-test: needs: [build-images, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.noir == 'true' }} + if: needs.changes.outputs.noir == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -422,7 +429,7 @@ jobs: noir-examples: needs: [build-images, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' }} + if: needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -435,7 +442,7 @@ jobs: noir-packages-test: needs: [build-images, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' }} + if: needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -449,7 +456,7 @@ jobs: noir-projects: needs: [build-images, changes, build] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' || needs.changes.outputs.noir-projects == 'true' }} + if: needs.changes.outputs.barretenberg == 'true' || needs.changes.outputs.noir == 'true' || needs.changes.outputs.noir-projects == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -464,7 +471,7 @@ jobs: avm-format: needs: [build-images, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.avm-transpiler == 'true' || needs.changes.outputs.noir == 'true' }} + if: needs.changes.outputs.avm-transpiler == 'true' || needs.changes.outputs.noir == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -518,7 +525,7 @@ jobs: l1-contracts-test: needs: [build-images, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.l1-contracts == 'true' }} + if: needs.changes.outputs.l1-contracts == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -531,7 +538,7 @@ jobs: docs-preview: needs: [build-images, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.non-barretenberg-cpp == 'true' }} + if: needs.changes.outputs.non-barretenberg-cpp == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -551,7 +558,7 @@ jobs: bb-bench: runs-on: ubuntu-20.04 needs: [build-images, changes] - if: ${{ needs.changes.outputs.barretenberg-cpp == 'true' }} + if: needs.changes.outputs.barretenberg-cpp == 'true' steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } @@ -579,7 +586,7 @@ jobs: # https://aztecprotocol.github.io/aztec-packages/dev/bench/ with new benchmark data. # This also creates an alert if benchmarks exceed the threshold specified below. - name: Store benchmark result - if: ${{ github.ref == 'refs/heads/master' }} + if: github.ref == 'refs/heads/master' uses: benchmark-action/github-action-benchmark@4de1bed97a47495fc4c5404952da0499e31f5c29 with: name: C++ Benchmark @@ -635,7 +642,7 @@ jobs: protocol-circuits-gates-report: needs: [build-images, changes] - if: ${{ needs.changes.outputs.non-docs == 'true' && needs.changes.outputs.non-misc-ci == 'true' }} + if: needs.changes.outputs.non-docs == 'true' && needs.changes.outputs.non-misc-ci == 'true' runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 permissions: pull-requests: write @@ -705,7 +712,8 @@ jobs: # - protocol-circuits-gates-report # non-blocking if: always() steps: - - name: Report overall success + - name: Report overall success (non-draft) + if: github.event.pull_request.draft == false env: # We treat any skipped or failing jobs as a failure for the workflow as a whole. FAIL: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} @@ -717,6 +725,9 @@ jobs: echo "All jobs succeeded, merge allowed." exit 0 fi + - name: Block merge (draft) + if: github.event.pull_request.draft + run: echo "Can't merge drafts." && exit 1 rerun-check: runs-on: ubuntu-20.04 @@ -754,7 +765,7 @@ jobs: - boxes - boxes-test # - protocol-circuits-gates-report # non-blocking - if: ${{ !cancelled() }} + if: github.event.pull_request.draft == false && !cancelled() steps: - name: Check for Rerun env: @@ -773,7 +784,7 @@ jobs: needs: - merge-check runs-on: ubuntu-20.04 - if: ${{ github.ref == 'refs/heads/master' && failure() && github.run_attempt >= 2 }} + if: github.event.pull_request.draft == false && github.ref == 'refs/heads/master' && failure() && github.run_attempt >= 2 steps: - name: Send notification to aztec3-ci channel if workflow failed on master uses: slackapi/slack-github-action@v1.25.0 diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 89166794d25..496f4f72833 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -515,7 +515,7 @@ jobs: run: | env terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/mainnet-fork" - terraform apply -input=false -auto-approve -replace="aws_efs_file_system.aztec_mainnet_fork_data_store" + terraform apply -input=false -auto-approve - name: Wait for mainnet fork deployment run: | @@ -567,13 +567,13 @@ jobs: working-directory: ./yarn-project/aztec/terraform/node run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/aztec-node" - terraform apply -input=false -auto-approve -replace="aws_efs_file_system.node_data_store" -var="NODE_P2P_TCP_PORT=${{ needs.set-network.outputs.node_tcp_range_start }}" -var="NODE_P2P_UDP_PORT=${{ needs.set-network.outputs.node_udp_range_start }}" + terraform apply -input=false -auto-approve -var="NODE_P2P_TCP_PORT=${{ needs.set-network.outputs.node_tcp_range_start }}" -var="NODE_P2P_UDP_PORT=${{ needs.set-network.outputs.node_udp_range_start }}" - name: Deploy Aztec Prover Nodes working-directory: ./yarn-project/aztec/terraform/prover-node run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/aztec-prover-node" - terraform apply -input=false -auto-approve -replace="aws_efs_file_system.prover_node_data_store" -var="NODE_P2P_TCP_PORT=${{ needs.set-network.outputs.prover_node_tcp_range_start }}" -var="NODE_P2P_UDP_PORT=${{ needs.set-network.outputs.prover_node_udp_range_start }}" + terraform apply -input=false -auto-approve -var="NODE_P2P_TCP_PORT=${{ needs.set-network.outputs.prover_node_tcp_range_start }}" -var="NODE_P2P_UDP_PORT=${{ needs.set-network.outputs.prover_node_udp_range_start }}" - name: Deploy Provers working-directory: ./yarn-project/aztec/terraform/prover diff --git a/.github/workflows/spartan-test.yml b/.github/workflows/spartan-test.yml index 902c032b647..6ed63e39900 100644 --- a/.github/workflows/spartan-test.yml +++ b/.github/workflows/spartan-test.yml @@ -111,7 +111,7 @@ jobs: run: | earthly-ci ./yarn-project+export-e2e-test-images - network-e2e: + test: needs: [build, changes] if: ${{ needs.changes.outputs.non-barretenberg-cpp == 'true' }} runs-on: ubuntu-20.04 @@ -145,7 +145,7 @@ jobs: success-check: runs-on: ubuntu-20.04 needs: - - build-and-test + - test if: always() steps: - name: Report overall success diff --git a/.noir-sync-commit b/.noir-sync-commit index d1dde8703df..f2fa0b3c445 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -e84f7d2e81c1f59e9af015f38c2d477607a9c558 +3c3ed1e3d28946a02071c524dd128afe131bc3da diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a290c0c736e..91c94e2e1da 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,7 +1,7 @@ { - ".": "0.52.0", + ".": "0.54.0", "yarn-project/cli": "0.35.1", - "yarn-project/aztec": "0.52.0", - "barretenberg": "0.52.0", - "barretenberg/ts": "0.52.0" + "yarn-project/aztec": "0.54.0", + "barretenberg": "0.54.0", + "barretenberg/ts": "0.54.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index b53493b3085..bbe5ab63a6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,215 @@ # Changelog +## [0.54.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.53.0...aztec-packages-v0.54.0) (2024-09-10) + + +### ⚠ BREAKING CHANGES + +* **avm:** variants for binary operations ([#8473](https://github.com/AztecProtocol/aztec-packages/issues/8473)) +* **avm:** make JUMP(I) 16-bit ([#8443](https://github.com/AztecProtocol/aztec-packages/issues/8443)) +* **avm:** variants for SET opcode ([#8441](https://github.com/AztecProtocol/aztec-packages/issues/8441)) +* **avm:** variants for MOV opcode ([#8440](https://github.com/AztecProtocol/aztec-packages/issues/8440)) + +### Features + +* (bb) 128-bit challenges ([#8406](https://github.com/AztecProtocol/aztec-packages/issues/8406)) ([d5b2397](https://github.com/AztecProtocol/aztec-packages/commit/d5b239745178d1ce4eb8b8d32fa4b366c13c3c94)) +* `Module::add_item` (https://github.com/noir-lang/noir/pull/5947) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Add `Expr::as_let` (https://github.com/noir-lang/noir/pull/5964) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Add `FunctionDefinition::module` and `StructDefinition::module` (https://github.com/noir-lang/noir/pull/5956) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Add `FunctionDefinition` methods `is_unconstrained` and `set_unconstrained` (https://github.com/noir-lang/noir/pull/5962) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Add `StructDefinition::add_generic` (https://github.com/noir-lang/noir/pull/5961) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Add `StructDefinition::name` (https://github.com/noir-lang/noir/pull/5960) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Add a `panic` method to the stdlib (https://github.com/noir-lang/noir/pull/5966) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Archiver fork block num ([#8425](https://github.com/AztecProtocol/aztec-packages/issues/8425)) ([a9f2364](https://github.com/AztecProtocol/aztec-packages/commit/a9f2364264e5cba4d01f09ef18801dd5ff39ae87)) +* Arithmetic Generics (https://github.com/noir-lang/noir/pull/5950) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* **avm-transpiler:** Optionally count opcode types ([#8439](https://github.com/AztecProtocol/aztec-packages/issues/8439)) ([21c06b5](https://github.com/AztecProtocol/aztec-packages/commit/21c06b5c497cea2ec1a0be457204508bc39516a6)) +* **avm/public:** User space PublicContext::get_args_hash ([#8292](https://github.com/AztecProtocol/aztec-packages/issues/8292)) ([56ce16a](https://github.com/AztecProtocol/aztec-packages/commit/56ce16a104476e070a627a5f0c5dcb3425691bcd)) +* **avm:** DSL integration of AVM recursive verifier ([#8405](https://github.com/AztecProtocol/aztec-packages/issues/8405)) ([467120e](https://github.com/AztecProtocol/aztec-packages/commit/467120e5a95de267910c2f95b65dcb62c60f995d)), closes [#8285](https://github.com/AztecProtocol/aztec-packages/issues/8285) +* **avm:** Make JUMP(I) 16-bit ([#8443](https://github.com/AztecProtocol/aztec-packages/issues/8443)) ([5bb38b1](https://github.com/AztecProtocol/aztec-packages/commit/5bb38b1692469520f29a1c85bc381c1ca9eb4032)) +* **avm:** Variants for binary operations ([#8473](https://github.com/AztecProtocol/aztec-packages/issues/8473)) ([8de1f2a](https://github.com/AztecProtocol/aztec-packages/commit/8de1f2a942024aad955ea0f318cb044e3692b7fc)) +* **avm:** Variants for MOV opcode ([#8440](https://github.com/AztecProtocol/aztec-packages/issues/8440)) ([5b27fbc](https://github.com/AztecProtocol/aztec-packages/commit/5b27fbca982442251a350d6571bdd007b715d575)) +* **avm:** Variants for SET opcode ([#8441](https://github.com/AztecProtocol/aztec-packages/issues/8441)) ([dc43306](https://github.com/AztecProtocol/aztec-packages/commit/dc433064391b2ac93bca6b838adac271fbd28991)) +* **bb:** Towards reduced polynomial memory usage ([#7990](https://github.com/AztecProtocol/aztec-packages/issues/7990)) ([372f23c](https://github.com/AztecProtocol/aztec-packages/commit/372f23ce0aa44a3aa6e1ef2f864df303a3229e6b)) +* Let `nargo` and LSP work well in the stdlib (https://github.com/noir-lang/noir/pull/5969) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* LSP autocompletion for attributes (https://github.com/noir-lang/noir/pull/5963) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* LSP now suggests self fields and methods (https://github.com/noir-lang/noir/pull/5955) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Show doc comments in LSP (https://github.com/noir-lang/noir/pull/5968) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) + + +### Bug Fixes + +* Add re-exports back ([#8453](https://github.com/AztecProtocol/aztec-packages/issues/8453)) ([b6cab90](https://github.com/AztecProtocol/aztec-packages/commit/b6cab90428be1b3576cbfedf17ab287fd9a659c8)) +* **avm:** Full proving kernel fix ([#8468](https://github.com/AztecProtocol/aztec-packages/issues/8468)) ([684d962](https://github.com/AztecProtocol/aztec-packages/commit/684d96271669116380facfa48db6cba3a5d945de)) +* **bb:** Mac release ([#8450](https://github.com/AztecProtocol/aztec-packages/issues/8450)) ([1b3f914](https://github.com/AztecProtocol/aztec-packages/commit/1b3f914fc069ec84fbd93621eb369128c3ba0dc5)) +* **docs:** Some docs updates ([#8412](https://github.com/AztecProtocol/aztec-packages/issues/8412)) ([ad73f30](https://github.com/AztecProtocol/aztec-packages/commit/ad73f304147027c8720b9720d92d2d8c409f599d)) +* Error when `quote` is used in runtime code (https://github.com/noir-lang/noir/pull/5978) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Error when comptime functions are used in runtime code (https://github.com/noir-lang/noir/pull/5976) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Fmt ([#8454](https://github.com/AztecProtocol/aztec-packages/issues/8454)) ([34b4a8a](https://github.com/AztecProtocol/aztec-packages/commit/34b4a8a012d373a0f2d2f10252e29d8201b8c003)) +* Guesstimate gas for propose ([#8445](https://github.com/AztecProtocol/aztec-packages/issues/8445)) ([bff0338](https://github.com/AztecProtocol/aztec-packages/commit/bff03382fc5f4be00ba0481564416f643b864f40)) +* Let `derive(Eq)` work for empty structs (https://github.com/noir-lang/noir/pull/5965) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* LSP document symbol didn't work for primitive impls (https://github.com/noir-lang/noir/pull/5970) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* **mem2reg:** Handle aliases better when setting a known value for a load (https://github.com/noir-lang/noir/pull/5959) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* **mem2reg:** Handle aliases in function last store cleanup and additional alias unit test (https://github.com/noir-lang/noir/pull/5967) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Public data reads and writes verification ([#8296](https://github.com/AztecProtocol/aztec-packages/issues/8296)) ([ae86347](https://github.com/AztecProtocol/aztec-packages/commit/ae863471fed30ea3382aea8223d7ddf8e9eef4ee)) +* Restrict keccak256_injective test input to 8 bits (https://github.com/noir-lang/noir/pull/5977) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Suggest trait attributes in LSP (https://github.com/noir-lang/noir/pull/5972) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) + + +### Miscellaneous + +* **bb:** Remove poly downsizing, other fast-follow from structured polys ([#8475](https://github.com/AztecProtocol/aztec-packages/issues/8475)) ([ac88f30](https://github.com/AztecProtocol/aztec-packages/commit/ac88f30808199c2625f889671f2767c3667becb5)) +* **ci:** Rerun ci when ready for review + don't allow draft merge ([#8456](https://github.com/AztecProtocol/aztec-packages/issues/8456)) ([ede16d3](https://github.com/AztecProtocol/aztec-packages/commit/ede16d31d99eb633630b037dc668e7c9b21ac769)) +* **docs:** Update box readme, remove duplicated features, added box install to the docs ([#8254](https://github.com/AztecProtocol/aztec-packages/issues/8254)) ([b747ac1](https://github.com/AztecProtocol/aztec-packages/commit/b747ac192bf63b2395c464f5b012ded9a3412846)) +* Document BoundedVec (https://github.com/noir-lang/noir/pull/5974) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Document HashMap (https://github.com/noir-lang/noir/pull/5984) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Merge devnet to master ([#8472](https://github.com/AztecProtocol/aztec-packages/issues/8472)) ([26706e9](https://github.com/AztecProtocol/aztec-packages/commit/26706e9d4339e6cf7603b6c86f1e7a1d3942bd63)) +* Remove 3 unused functions warnings in the stdlib (https://github.com/noir-lang/noir/pull/5973) ([8ac81b1](https://github.com/AztecProtocol/aztec-packages/commit/8ac81b15cd2a3b57493bfbfe444086deac8f3dc8)) +* Remove warnings from protocol circuits ([#8420](https://github.com/AztecProtocol/aztec-packages/issues/8420)) ([c4dbcab](https://github.com/AztecProtocol/aztec-packages/commit/c4dbcabf48e930b2c541a1d98d8c1e3807f4f4fc)) +* Rename files relating to what were "instances" ([#8383](https://github.com/AztecProtocol/aztec-packages/issues/8383)) ([a934e85](https://github.com/AztecProtocol/aztec-packages/commit/a934e85b416a029ae057e0e70277401fb7cfe4b9)) +* Replace relative paths to noir-protocol-circuits ([1c43bae](https://github.com/AztecProtocol/aztec-packages/commit/1c43bae21fbe909eff62d1f7ebb5789fbfa8bef3)) + +## [0.53.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.52.0...aztec-packages-v0.53.0) (2024-09-09) + + +### ⚠ BREAKING CHANGES + +* **avm/brillig:** take addresses in calldatacopy ([#8388](https://github.com/AztecProtocol/aztec-packages/issues/8388)) +* remove coinbase and unimplemented block gas limit opcodes from AVM ([#8408](https://github.com/AztecProtocol/aztec-packages/issues/8408)) +* return arrays instead of slices from `to_be_radix` functions (https://github.com/noir-lang/noir/pull/5851) +* Do not encode assertion strings in the programs ([#8315](https://github.com/AztecProtocol/aztec-packages/issues/8315)) + +### Features + +* `Module::add_item` (https://github.com/noir-lang/noir/pull/5947) ([075036e](https://github.com/AztecProtocol/aztec-packages/commit/075036e41d7a2a5558b29f205ccd8b3506d6d473)) +* Add `Expr::as_assert_eq` (https://github.com/noir-lang/noir/pull/5880) ([f8f4709](https://github.com/AztecProtocol/aztec-packages/commit/f8f4709fe4c7d6b99f7eb711a3e30ece98a3e052)) +* Add `fmtstr::contents` (https://github.com/noir-lang/noir/pull/5928) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* Add `FunctionDef::set_return_visibility` (https://github.com/noir-lang/noir/pull/5941) ([f3e4f97](https://github.com/AztecProtocol/aztec-packages/commit/f3e4f9734406eb58c52511b550cb99bdf28b13ea)) +* Add `FunctionDefinition::add_attribute` (https://github.com/noir-lang/noir/pull/5944) ([f3e4f97](https://github.com/AztecProtocol/aztec-packages/commit/f3e4f9734406eb58c52511b550cb99bdf28b13ea)) +* Add `FunctionDefinition::module` and `StructDefinition::module` (https://github.com/noir-lang/noir/pull/5956) ([075036e](https://github.com/AztecProtocol/aztec-packages/commit/075036e41d7a2a5558b29f205ccd8b3506d6d473)) +* Add `FunctionDefinition` methods `is_unconstrained` and `set_unconstrained` (https://github.com/noir-lang/noir/pull/5962) ([075036e](https://github.com/AztecProtocol/aztec-packages/commit/075036e41d7a2a5558b29f205ccd8b3506d6d473)) +* Add `Quoted::tokens` (https://github.com/noir-lang/noir/pull/5942) ([f3e4f97](https://github.com/AztecProtocol/aztec-packages/commit/f3e4f9734406eb58c52511b550cb99bdf28b13ea)) +* Add `std::meta::typ::fresh_type_variable` (https://github.com/noir-lang/noir/pull/5948) ([f3e4f97](https://github.com/AztecProtocol/aztec-packages/commit/f3e4f9734406eb58c52511b550cb99bdf28b13ea)) +* Add `StructDefinition::add_attribute` and `has_named_attribute` (https://github.com/noir-lang/noir/pull/5945) ([f3e4f97](https://github.com/AztecProtocol/aztec-packages/commit/f3e4f9734406eb58c52511b550cb99bdf28b13ea)) +* Add `StructDefinition::add_generic` (https://github.com/noir-lang/noir/pull/5961) ([075036e](https://github.com/AztecProtocol/aztec-packages/commit/075036e41d7a2a5558b29f205ccd8b3506d6d473)) +* Add `StructDefinition::name` (https://github.com/noir-lang/noir/pull/5960) ([075036e](https://github.com/AztecProtocol/aztec-packages/commit/075036e41d7a2a5558b29f205ccd8b3506d6d473)) +* Add `StructDefinition::set_fields` (https://github.com/noir-lang/noir/pull/5931) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* Add bot config to toggle simulation ([#8297](https://github.com/AztecProtocol/aztec-packages/issues/8297)) ([1c7c447](https://github.com/AztecProtocol/aztec-packages/commit/1c7c44742d0b3e6940ea08a42085d236fd209cad)) +* Add poseidon relations to UltraKeccak flavor and Solidity verifier ([#8243](https://github.com/AztecProtocol/aztec-packages/issues/8243)) ([f7e4bfb](https://github.com/AztecProtocol/aztec-packages/commit/f7e4bfb0fc8070b7b79366241f3d37357dfaee27)) +* Addressing Nico's router comments ([#8384](https://github.com/AztecProtocol/aztec-packages/issues/8384)) ([d582c93](https://github.com/AztecProtocol/aztec-packages/commit/d582c932888ffbf5d240f28c0d83d926e4cb7a51)) +* Allow inserting new structs and into programs from attributes (https://github.com/noir-lang/noir/pull/5927) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* Arithmetic Generics (https://github.com/noir-lang/noir/pull/5950) ([075036e](https://github.com/AztecProtocol/aztec-packages/commit/075036e41d7a2a5558b29f205ccd8b3506d6d473)) +* **avm/brillig:** Take addresses in calldatacopy ([#8388](https://github.com/AztecProtocol/aztec-packages/issues/8388)) ([eab944c](https://github.com/AztecProtocol/aztec-packages/commit/eab944cbb77eb613e61a879312b58c415f8a0c13)) +* Better println for Quoted (https://github.com/noir-lang/noir/pull/5896) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* Calculate `FunctionSelector`s and `EventSelector`s during comptime ([#8354](https://github.com/AztecProtocol/aztec-packages/issues/8354)) ([52258b1](https://github.com/AztecProtocol/aztec-packages/commit/52258b11f3e2f58631f4d77bd0bf00034512dc73)) +* Check argument count and types on attribute function callback (https://github.com/noir-lang/noir/pull/5921) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* **ci:** Tracy gate counter preset ([#8382](https://github.com/AztecProtocol/aztec-packages/issues/8382)) ([882af1e](https://github.com/AztecProtocol/aztec-packages/commit/882af1ed821c135b68a5d693a81b7fc580ad97c2)) +* Do not encode assertion strings in the programs ([#8315](https://github.com/AztecProtocol/aztec-packages/issues/8315)) ([f5bbb89](https://github.com/AztecProtocol/aztec-packages/commit/f5bbb89b489bc85f286bcc5ed45c30f38032810c)) +* Implement `str_as_bytes` in the `comptime` interpreter (https://github.com/noir-lang/noir/pull/5887) ([f8f4709](https://github.com/AztecProtocol/aztec-packages/commit/f8f4709fe4c7d6b99f7eb711a3e30ece98a3e052)) +* Liveness analysis for constants ([#8294](https://github.com/AztecProtocol/aztec-packages/issues/8294)) ([0330ced](https://github.com/AztecProtocol/aztec-packages/commit/0330ced124d5455cc584694255a3ceed9c35b69f)) +* LSP autocompletion for attributes (https://github.com/noir-lang/noir/pull/5963) ([075036e](https://github.com/AztecProtocol/aztec-packages/commit/075036e41d7a2a5558b29f205ccd8b3506d6d473)) +* LSP code action "Fill struct fields" (https://github.com/noir-lang/noir/pull/5885) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* LSP code actions to import or qualify unresolved paths (https://github.com/noir-lang/noir/pull/5876) ([f8f4709](https://github.com/AztecProtocol/aztec-packages/commit/f8f4709fe4c7d6b99f7eb711a3e30ece98a3e052)) +* LSP diagnostics for all package files (https://github.com/noir-lang/noir/pull/5895) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* LSP diagnostics now have "unnecessary" and "deprecated" tags (https://github.com/noir-lang/noir/pull/5878) ([f8f4709](https://github.com/AztecProtocol/aztec-packages/commit/f8f4709fe4c7d6b99f7eb711a3e30ece98a3e052)) +* LSP now suggests self fields and methods (https://github.com/noir-lang/noir/pull/5955) ([075036e](https://github.com/AztecProtocol/aztec-packages/commit/075036e41d7a2a5558b29f205ccd8b3506d6d473)) +* LSP will now suggest private items if they are visible (https://github.com/noir-lang/noir/pull/5923) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* Module attributes (https://github.com/noir-lang/noir/pull/5888) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* Only check array bounds in brillig if index is unsafe (https://github.com/noir-lang/noir/pull/5938) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* **perf:** Remove known store values that equal the store address in mem2reg (https://github.com/noir-lang/noir/pull/5935) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* **perf:** Remove last store in return block if last load is before that store (https://github.com/noir-lang/noir/pull/5910) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* Remove blocks which consist of only a jump to another block (https://github.com/noir-lang/noir/pull/5889) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* Replace arithmetic equalities with assert equal ([#8386](https://github.com/AztecProtocol/aztec-packages/issues/8386)) ([0d8e835](https://github.com/AztecProtocol/aztec-packages/commit/0d8e835dd6cd6cd545edda20f652ab6f10c530da)) +* Return arrays instead of slices from `to_be_radix` functions (https://github.com/noir-lang/noir/pull/5851) ([f8f4709](https://github.com/AztecProtocol/aztec-packages/commit/f8f4709fe4c7d6b99f7eb711a3e30ece98a3e052)) +* Router contract ([#8352](https://github.com/AztecProtocol/aztec-packages/issues/8352)) ([138dc52](https://github.com/AztecProtocol/aztec-packages/commit/138dc52a232f20248306aa9a99cf66f0ac7ec7eb)) +* Sequencer selection in k8s tests ([#8313](https://github.com/AztecProtocol/aztec-packages/issues/8313)) ([8d9947d](https://github.com/AztecProtocol/aztec-packages/commit/8d9947d3584b2596d7d4e0d75e8534efc9fab7a4)) +* Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5877) ([27e4761](https://github.com/AztecProtocol/aztec-packages/commit/27e476119021c4fe4f6e4e8cb53947215458d4d0)) +* Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5883) ([f8f4709](https://github.com/AztecProtocol/aztec-packages/commit/f8f4709fe4c7d6b99f7eb711a3e30ece98a3e052)) +* Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5917) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5951) ([f3e4f97](https://github.com/AztecProtocol/aztec-packages/commit/f3e4f9734406eb58c52511b550cb99bdf28b13ea)) +* Track proving times in prover stats in CLI ([#8281](https://github.com/AztecProtocol/aztec-packages/issues/8281)) ([efad298](https://github.com/AztecProtocol/aztec-packages/commit/efad298f60a86094394fd4ac67fbf108fba110f9)) +* Tuple return value typescript decoding ([#8319](https://github.com/AztecProtocol/aztec-packages/issues/8319)) ([b09a1bb](https://github.com/AztecProtocol/aztec-packages/commit/b09a1bbcc31ac0af5f23e7c9677ef922d5da5239)) +* Ultra keccak honk verifier ([#8261](https://github.com/AztecProtocol/aztec-packages/issues/8261)) ([7f02900](https://github.com/AztecProtocol/aztec-packages/commit/7f029007365b57c06699914f97b93d0891d2a6f1)) +* Unquote some value as tokens, not as unquote markers (https://github.com/noir-lang/noir/pull/5924) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* Update AztecIvc interface to facilitate acir-ivc ([#8230](https://github.com/AztecProtocol/aztec-packages/issues/8230)) ([665750a](https://github.com/AztecProtocol/aztec-packages/commit/665750a8d7f20ea4e3f7cded052b88eb6bb28600)) +* Use visibility (https://github.com/noir-lang/noir/pull/5856) ([f8f4709](https://github.com/AztecProtocol/aztec-packages/commit/f8f4709fe4c7d6b99f7eb711a3e30ece98a3e052)) +* Verify public validation requests ([#8150](https://github.com/AztecProtocol/aztec-packages/issues/8150)) ([2be1415](https://github.com/AztecProtocol/aztec-packages/commit/2be14157abe3b277c58780ecc03bb1eff8dec20e)) +* Warn on unused functions (https://github.com/noir-lang/noir/pull/5892) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) + + +### Bug Fixes + +* Address issues when using wall-time ([#8329](https://github.com/AztecProtocol/aztec-packages/issues/8329)) ([639fb3b](https://github.com/AztecProtocol/aztec-packages/commit/639fb3b7225911f0051b73930755219473984581)) +* Always place module attribute generated items inside module (https://github.com/noir-lang/noir/pull/5943) ([f3e4f97](https://github.com/AztecProtocol/aztec-packages/commit/f3e4f9734406eb58c52511b550cb99bdf28b13ea)) +* Bot config for skip public simulation ([#8320](https://github.com/AztecProtocol/aztec-packages/issues/8320)) ([133b642](https://github.com/AztecProtocol/aztec-packages/commit/133b642b12ff03c71bd90a4acda10f484fe1b77f)) +* Broken build ([#8395](https://github.com/AztecProtocol/aztec-packages/issues/8395)) ([d0ea6eb](https://github.com/AztecProtocol/aztec-packages/commit/d0ea6ebbe8b4bb918acc2aa5a4c09863a93b7c08)) +* Collect functions generated by attributes (https://github.com/noir-lang/noir/pull/5930) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* Do not reuse anvil admin key ([#8304](https://github.com/AztecProtocol/aztec-packages/issues/8304)) ([6863fe5](https://github.com/AztecProtocol/aztec-packages/commit/6863fe5094193ce29118c8a315e38b7b3aea69ca)) +* **frontend:** Ban type vars bound to a reference from passing the unconstrained boundary (https://github.com/noir-lang/noir/pull/5949) ([f3e4f97](https://github.com/AztecProtocol/aztec-packages/commit/f3e4f9734406eb58c52511b550cb99bdf28b13ea)) +* HonkRecursion serde for cpp bindings ([#8387](https://github.com/AztecProtocol/aztec-packages/issues/8387)) ([6162179](https://github.com/AztecProtocol/aztec-packages/commit/6162179ffc9b04213ef600e1733d2ac696c1dbe6)) +* Increase timeout for Sepolia mining ([#8430](https://github.com/AztecProtocol/aztec-packages/issues/8430)) ([29369ed](https://github.com/AztecProtocol/aztec-packages/commit/29369ed65ab6a01a0b8c1a05b4f6b9710dd8e44b)) +* Let `derive(Eq)` work for empty structs (https://github.com/noir-lang/noir/pull/5965) ([075036e](https://github.com/AztecProtocol/aztec-packages/commit/075036e41d7a2a5558b29f205ccd8b3506d6d473)) +* **mem2reg:** Handle aliases better when setting a known value for a load (https://github.com/noir-lang/noir/pull/5959) ([075036e](https://github.com/AztecProtocol/aztec-packages/commit/075036e41d7a2a5558b29f205ccd8b3506d6d473)) +* **mem2reg:** Handle aliases in function last store cleanup and additional alias unit test (https://github.com/noir-lang/noir/pull/5967) ([075036e](https://github.com/AztecProtocol/aztec-packages/commit/075036e41d7a2a5558b29f205ccd8b3506d6d473)) +* Prevent comptime println from crashing LSP (https://github.com/noir-lang/noir/pull/5918) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* Revert "feat: ultra keccak honk verifier ([#8427](https://github.com/AztecProtocol/aztec-packages/issues/8427)) ([31df5ea](https://github.com/AztecProtocol/aztec-packages/commit/31df5ead9e182bcf57588438f1b73eba4c052fa5)) +* Revert "feat: ultra keccak honk verifier" ([#8391](https://github.com/AztecProtocol/aztec-packages/issues/8391)) ([3228e75](https://github.com/AztecProtocol/aztec-packages/commit/3228e7526aa30b514375c62264cbde578754cd79)) +* Split stores per component and split merkle tree operations ([#8299](https://github.com/AztecProtocol/aztec-packages/issues/8299)) ([4ee69ac](https://github.com/AztecProtocol/aztec-packages/commit/4ee69acf8588adb46d2e9369d5541fb04380c652)) +* SubscriptionNote preimage attack ([#8390](https://github.com/AztecProtocol/aztec-packages/issues/8390)) ([94006a9](https://github.com/AztecProtocol/aztec-packages/commit/94006a99229ed7e712fa2b7b2851ed2fb509dca0)) +* Support debug comptime flag for attributes (https://github.com/noir-lang/noir/pull/5929) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* Temporary register leaks in brillig gen ([#8350](https://github.com/AztecProtocol/aztec-packages/issues/8350)) ([5f6d2e2](https://github.com/AztecProtocol/aztec-packages/commit/5f6d2e27d0b9045b8e7e875317918bd09af40d8c)) +* Transpiler after noir sync ([#8353](https://github.com/AztecProtocol/aztec-packages/issues/8353)) ([249e50e](https://github.com/AztecProtocol/aztec-packages/commit/249e50efafd306fa8cd9005972636adbddbca81e)) +* TXE logs in docker ([#8365](https://github.com/AztecProtocol/aztec-packages/issues/8365)) ([157dd11](https://github.com/AztecProtocol/aztec-packages/commit/157dd118896e101d654110f8b519fb059c3e7f4f)) +* Use element_size() instead of computing it with division (https://github.com/noir-lang/noir/pull/5939) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* Wait for receipt ([#8358](https://github.com/AztecProtocol/aztec-packages/issues/8358)) ([8b7b2d2](https://github.com/AztecProtocol/aztec-packages/commit/8b7b2d2b8f13b0b8ebda1cd7e14ef2e9c18e0bac)) + + +### Miscellaneous + +* Add a span to track timing of brillig gen (https://github.com/noir-lang/noir/pull/5835) ([f8f4709](https://github.com/AztecProtocol/aztec-packages/commit/f8f4709fe4c7d6b99f7eb711a3e30ece98a3e052)) +* Add pass to normalize Ids in SSA (https://github.com/noir-lang/noir/pull/5909) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* Add uint (U128) note to aztec-nr and remove OwnedNote from ValueNote ([#8142](https://github.com/AztecProtocol/aztec-packages/issues/8142)) ([225b6d3](https://github.com/AztecProtocol/aztec-packages/commit/225b6d319d013ce41d6396ba01cd0968da074c4e)) +* **avm:** Move proving key to avm files ([#8318](https://github.com/AztecProtocol/aztec-packages/issues/8318)) ([32d67bd](https://github.com/AztecProtocol/aztec-packages/commit/32d67bd72244bfc3ea28aef7358c467a5b238b6b)) +* **avm:** Remove some unused deps ([#8366](https://github.com/AztecProtocol/aztec-packages/issues/8366)) ([e2150a7](https://github.com/AztecProtocol/aztec-packages/commit/e2150a7e5fc84932b65af07025514fc3c57f1cbc)) +* **bb:** Reinstate "chore: uncomment asserts in oink rec verifier"" ([#8356](https://github.com/AztecProtocol/aztec-packages/issues/8356)) ([4dbad01](https://github.com/AztecProtocol/aztec-packages/commit/4dbad01c866b28f7d440d7b4e17631ed6a0469f3)) +* **bb:** Use std::span for srs ([#8371](https://github.com/AztecProtocol/aztec-packages/issues/8371)) ([f174699](https://github.com/AztecProtocol/aztec-packages/commit/f1746999ea12cc8117efd5a0c3b2ec5d80196343)) +* Bump some dependencies (https://github.com/noir-lang/noir/pull/5893) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* Change efs volumes to use bursting throughput ([#8370](https://github.com/AztecProtocol/aztec-packages/issues/8370)) ([d6ebe3e](https://github.com/AztecProtocol/aztec-packages/commit/d6ebe3e674ea59acf810c9736aa908c63b5a9b85)) +* **ci:** Don't run on draft PRs ([#8426](https://github.com/AztecProtocol/aztec-packages/issues/8426)) ([8abe6c8](https://github.com/AztecProtocol/aztec-packages/commit/8abe6c83522c65b1ff0b29f670c6b2e7cb725b2a)) +* **ci:** Skip vk generation on `protocol-circuits-gates-report` and `noir-format` ([#8398](https://github.com/AztecProtocol/aztec-packages/issues/8398)) ([824aa8a](https://github.com/AztecProtocol/aztec-packages/commit/824aa8ab9d5c5f6b1b69c35a40eb7e0735ab1f23)) +* **ci:** Test lowering of non-persistent ebs provisions ([#8360](https://github.com/AztecProtocol/aztec-packages/issues/8360)) ([8ee8595](https://github.com/AztecProtocol/aztec-packages/commit/8ee8595d664d7c1dca65bd0496648bb4cf1a32f7)) +* Cleanup str_as_bytes (https://github.com/noir-lang/noir/pull/5900) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* Delete more unwanted stuff from noir code ([#8335](https://github.com/AztecProtocol/aztec-packages/issues/8335)) ([d2a8aa4](https://github.com/AztecProtocol/aztec-packages/commit/d2a8aa47f36c3dd5ae6ec287550d38ad9ca0c104)) +* **docs:** Cli wallet ([#8182](https://github.com/AztecProtocol/aztec-packages/issues/8182)) ([7298c8f](https://github.com/AztecProtocol/aztec-packages/commit/7298c8f54460f506ecb959658d9cfd4f1129ef01)) +* **docs:** Fix migration notes ([#8447](https://github.com/AztecProtocol/aztec-packages/issues/8447)) ([1e91469](https://github.com/AztecProtocol/aztec-packages/commit/1e9146942507baf738ce2711129fe527a4d4d142)) +* Error on false constraint (https://github.com/noir-lang/noir/pull/5890) ([05cc59f](https://github.com/AztecProtocol/aztec-packages/commit/05cc59fd28b4d0ee89343106e538c0db0e70f52f)) +* Fix some instances of missing unsafe blocks ([#8232](https://github.com/AztecProtocol/aztec-packages/issues/8232)) ([e8e0907](https://github.com/AztecProtocol/aztec-packages/commit/e8e09077deba33d805cfecafbbe67b8d61c6cc8a)) +* Fix spartan test nightly runner ([#8433](https://github.com/AztecProtocol/aztec-packages/issues/8433)) ([a34f353](https://github.com/AztecProtocol/aztec-packages/commit/a34f35311ace0f06e22da111d72467dd976fdd8d)) +* Improve ec addition ([#8291](https://github.com/AztecProtocol/aztec-packages/issues/8291)) ([e8a097c](https://github.com/AztecProtocol/aztec-packages/commit/e8a097cf338bae2445006b3f20a2f54fc8f5e7f5)) +* Increase AZTEC_SLOT_DURATION ([#8331](https://github.com/AztecProtocol/aztec-packages/issues/8331)) ([5d48500](https://github.com/AztecProtocol/aztec-packages/commit/5d485006cf9fdf20b4081da1b203edf7abe1675f)) +* Make nested slice error more clear for `[[T]; N]` case (https://github.com/noir-lang/noir/pull/5906) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* Merge provernet to master ([#8373](https://github.com/AztecProtocol/aztec-packages/issues/8373)) ([e1dc987](https://github.com/AztecProtocol/aztec-packages/commit/e1dc9878de06a1f3d4cde9bbcf652ac342951d52)) +* More efficient verification with shplonk and gemini ([#8351](https://github.com/AztecProtocol/aztec-packages/issues/8351)) ([e51d157](https://github.com/AztecProtocol/aztec-packages/commit/e51d157fc7ae9a8ffeba8e6f89dbe87034d36db4)) +* Move spartan network tests to nightly ([#8369](https://github.com/AztecProtocol/aztec-packages/issues/8369)) ([8fe045c](https://github.com/AztecProtocol/aztec-packages/commit/8fe045ca3c25997f1eda874dec0da67b7d564d06)) +* No assert in `is_valid_impl(...)` ([#8397](https://github.com/AztecProtocol/aztec-packages/issues/8397)) ([1c1d35a](https://github.com/AztecProtocol/aztec-packages/commit/1c1d35ae8ace593e2b336b0a5172be68534dad68)) +* Pw/devnet fixes ([#8385](https://github.com/AztecProtocol/aztec-packages/issues/8385)) ([4fb4e17](https://github.com/AztecProtocol/aztec-packages/commit/4fb4e178d7cd6de999455b624ec4d3b6b63fceb7)) +* Redo typo PR by FilipHarald ([#8418](https://github.com/AztecProtocol/aztec-packages/issues/8418)) ([2894b68](https://github.com/AztecProtocol/aztec-packages/commit/2894b68022981fcc5771c11acfd213d51446f96b)) +* Redo typo PR by operagxsasha ([#8429](https://github.com/AztecProtocol/aztec-packages/issues/8429)) ([a1060a3](https://github.com/AztecProtocol/aztec-packages/commit/a1060a3ad4cbf0e070c45a7a1a309b91529f5ff3)) +* Remove coinbase and unimplemented block gas limit opcodes from AVM ([#8408](https://github.com/AztecProtocol/aztec-packages/issues/8408)) ([dd09b76](https://github.com/AztecProtocol/aztec-packages/commit/dd09b76f70420a3824bf406bb2044481f68cd741)) +* Remove equality operation on boolean constraints against constants (https://github.com/noir-lang/noir/pull/5919) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* Remove override to use rust syntax highlighting (https://github.com/noir-lang/noir/pull/5881) ([f3e4f97](https://github.com/AztecProtocol/aztec-packages/commit/f3e4f9734406eb58c52511b550cb99bdf28b13ea)) +* Remove unimplemented headermember opcode from avm ([#8407](https://github.com/AztecProtocol/aztec-packages/issues/8407)) ([cfea06e](https://github.com/AztecProtocol/aztec-packages/commit/cfea06ed72449a62e21ba4b0f1b0d77200f91635)) +* Renaming `Instance`'s ([#8362](https://github.com/AztecProtocol/aztec-packages/issues/8362)) ([4789440](https://github.com/AztecProtocol/aztec-packages/commit/478944010ca8f28eabba733d04a9a8e9a43c29a9)) +* Replace relative paths to noir-protocol-circuits ([3c9d85e](https://github.com/AztecProtocol/aztec-packages/commit/3c9d85e67eb547d617e44d2ab5a1579242adccb0)) +* Replace relative paths to noir-protocol-circuits ([69b1754](https://github.com/AztecProtocol/aztec-packages/commit/69b1754ddddc7831960eb6f9dc26cfc58b056392)) +* Replace relative paths to noir-protocol-circuits ([feff126](https://github.com/AztecProtocol/aztec-packages/commit/feff126409a81148daea517e5d4acc7a6ec458c5)) +* Replace relative paths to noir-protocol-circuits ([3d58d36](https://github.com/AztecProtocol/aztec-packages/commit/3d58d361413bb5e3a66831c333e94715985f34a5)) +* Replace relative paths to noir-protocol-circuits ([7c15ac4](https://github.com/AztecProtocol/aztec-packages/commit/7c15ac43d87eb0fa15f7e1ebdf91728924dc0536)) +* **revert:** "chore(ci): Test lowering of non-persistent ebs provisions" ([#8392](https://github.com/AztecProtocol/aztec-packages/issues/8392)) ([2ea6ec2](https://github.com/AztecProtocol/aztec-packages/commit/2ea6ec21a9013978e589a9f5bd3a064236359e45)) +* Send anvil logs to stdout ([#8311](https://github.com/AztecProtocol/aztec-packages/issues/8311)) ([6a2614a](https://github.com/AztecProtocol/aztec-packages/commit/6a2614a94a7b049e8aecaaa900b0a067dd2e15dd)) +* Uncomment asserts in oink rec verifier ([#8316](https://github.com/AztecProtocol/aztec-packages/issues/8316)) ([a7f3144](https://github.com/AztecProtocol/aztec-packages/commit/a7f314448215950f6f1a7d4f282359df040be502)) +* Update git user for release PRs (https://github.com/noir-lang/noir/pull/5894) ([176bce6](https://github.com/AztecProtocol/aztec-packages/commit/176bce6dd1a4dfbbd82d4f83fddbb02f84145765)) +* Use `new_let` more widely (https://github.com/noir-lang/noir/pull/5882) ([f8f4709](https://github.com/AztecProtocol/aztec-packages/commit/f8f4709fe4c7d6b99f7eb711a3e30ece98a3e052)) + ## [0.52.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.51.1...aztec-packages-v0.52.0) (2024-09-01) diff --git a/README.md b/README.md index ae5156f1d04..cc6b62484a8 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Recovering if the sync is not happening with basic pull commands: - manually editing the commit variable in noir/noir-repo/.gitrepo: this needs to exist in the branch we push to, and have the same content as our base. This is similar to submodules, except instead of pointing to the final state of the module, it points to the last commit we have sync'd from, for purposes of commit replay. This can be fixed to match the commit in master after merges. -- manually editing the parent variable in noir/noir-repo/.gitrepo: this is the parent of the last sync commit on aztec side. If you get errors with a commit not being found in the upstream repo, and the commit mentioned is not the commit variable above, it might indicate this is somehow incorrect. This can happen when commit content is ported without its history, e.g. squashes +- manually editing the parent variable in noir/noir-repo/.gitrepo: this is the parent of the last sync commit on aztec side. If you get errors with a commit not being found in the upstream repo, and the commit mentioned is not the commit variable above, it might indicate this is somehow incorrect. This can happen when commit content is ported without its history, e.g. squashes. - use pull --force ONLY where you would use git reset. That is, if you really want to match some upstream noir for a purpose its fine, but you'll lose local changes (if any) ## Earthly diff --git a/avm-transpiler/src/bit_traits.rs b/avm-transpiler/src/bit_traits.rs new file mode 100644 index 00000000000..ff54ef23df5 --- /dev/null +++ b/avm-transpiler/src/bit_traits.rs @@ -0,0 +1,74 @@ +use acvm::{AcirField, FieldElement}; + +fn get_msb(n: u128) -> usize { + let mut n = n; + let mut msb = 0; + while n > 0 { + n >>= 1; + msb += 1; + } + msb +} + +pub trait BitsQueryable { + fn num_bits(&self) -> usize; +} + +impl BitsQueryable for FieldElement { + fn num_bits(&self) -> usize { + AcirField::num_bits(self) as usize + } +} + +impl BitsQueryable for u8 { + fn num_bits(&self) -> usize { + get_msb(*self as u128) + } +} + +impl BitsQueryable for u16 { + fn num_bits(&self) -> usize { + get_msb(*self as u128) + } +} + +impl BitsQueryable for u32 { + fn num_bits(&self) -> usize { + get_msb(*self as u128) + } +} + +impl BitsQueryable for u64 { + fn num_bits(&self) -> usize { + get_msb(*self as u128) + } +} + +impl BitsQueryable for u128 { + fn num_bits(&self) -> usize { + get_msb(*self) + } +} + +impl BitsQueryable for usize { + fn num_bits(&self) -> usize { + get_msb(*self as u128) + } +} + +pub fn bits_needed_for(val: &T) -> usize { + let num_bits = val.num_bits(); + if num_bits < 8 { + 8 + } else if num_bits < 16 { + 16 + } else if num_bits < 32 { + 32 + } else if num_bits < 64 { + 64 + } else if num_bits < 128 { + 128 + } else { + 254 + } +} diff --git a/avm-transpiler/src/instructions.rs b/avm-transpiler/src/instructions.rs index f2e56b451eb..0e25dedc3f3 100644 --- a/avm-transpiler/src/instructions.rs +++ b/avm-transpiler/src/instructions.rs @@ -1,6 +1,8 @@ use std::fmt::{self, Display}; use std::fmt::{Debug, Formatter}; +use acvm::{AcirField, FieldElement}; + use crate::opcodes::AvmOpcode; /// Common values of the indirect instruction flag @@ -78,7 +80,7 @@ impl Debug for AvmInstruction { impl Default for AvmInstruction { fn default() -> Self { AvmInstruction { - opcode: AvmOpcode::ADD, + opcode: AvmOpcode::ADD_8, // TODO(4266): default to Some(0), since all instructions have indirect flag except jumps indirect: None, tag: None, @@ -110,6 +112,7 @@ pub enum AvmOperand { U32 { value: u32 }, U64 { value: u64 }, U128 { value: u128 }, + FF { value: FieldElement }, } impl Display for AvmOperand { @@ -120,6 +123,7 @@ impl Display for AvmOperand { AvmOperand::U32 { value } => write!(f, " U32:{}", value), AvmOperand::U64 { value } => write!(f, " U64:{}", value), AvmOperand::U128 { value } => write!(f, " U128:{}", value), + AvmOperand::FF { value } => write!(f, " FF:{}", value), } } } @@ -132,6 +136,7 @@ impl AvmOperand { AvmOperand::U32 { value } => value.to_be_bytes().to_vec(), AvmOperand::U64 { value } => value.to_be_bytes().to_vec(), AvmOperand::U128 { value } => value.to_be_bytes().to_vec(), + AvmOperand::FF { value } => value.to_be_bytes(), } } } diff --git a/avm-transpiler/src/main.rs b/avm-transpiler/src/main.rs index 384348fc463..27a848ac231 100644 --- a/avm-transpiler/src/main.rs +++ b/avm-transpiler/src/main.rs @@ -6,6 +6,7 @@ use std::env; use std::fs; use std::path::Path; +mod bit_traits; mod instructions; mod opcodes; mod transpile; diff --git a/avm-transpiler/src/opcodes.rs b/avm-transpiler/src/opcodes.rs index f75508bd33a..f06cece6b7d 100644 --- a/avm-transpiler/src/opcodes.rs +++ b/avm-transpiler/src/opcodes.rs @@ -1,23 +1,36 @@ /// All AVM opcodes /// Keep updated with TS, cpp, and docs protocol specs! -#[allow(clippy::upper_case_acronyms, dead_code)] -#[derive(PartialEq, Copy, Clone, Debug)] +#[allow(clippy::upper_case_acronyms, dead_code, non_camel_case_types)] +#[derive(PartialEq, Copy, Clone, Debug, Eq, Hash)] pub enum AvmOpcode { // Compute - ADD, - SUB, - MUL, - DIV, - FDIV, - EQ, - LT, - LTE, - AND, - OR, - XOR, + ADD_8, + ADD_16, + SUB_8, + SUB_16, + MUL_8, + MUL_16, + DIV_8, + DIV_16, + FDIV_8, + FDIV_16, + EQ_8, + EQ_16, + LT_8, + LT_16, + LTE_8, + LTE_16, + AND_8, + AND_16, + OR_8, + OR_16, + XOR_8, + XOR_16, NOT, - SHL, - SHR, + SHL_8, + SHL_16, + SHR_8, + SHR_16, CAST, // Execution environment ADDRESS, @@ -29,23 +42,26 @@ pub enum AvmOpcode { VERSION, BLOCKNUMBER, TIMESTAMP, - COINBASE, FEEPERL2GAS, FEEPERDAGAS, - BLOCKL2GASLIMIT, - BLOCKDAGASLIMIT, CALLDATACOPY, // Gas L2GASLEFT, DAGASLEFT, // Control flow - JUMP, - JUMPI, + JUMP_16, + JUMPI_16, INTERNALCALL, INTERNALRETURN, // Memory - SET, - MOV, + SET_8, + SET_16, + SET_32, + SET_64, + SET_128, + SET_FF, + MOV_8, + MOV_16, CMOV, // World state SLOAD, @@ -86,22 +102,35 @@ impl AvmOpcode { match self { // Compute // Compute - Arithmetic - AvmOpcode::ADD => "ADD", - AvmOpcode::SUB => "SUB", - AvmOpcode::MUL => "MUL", - AvmOpcode::DIV => "DIV", - AvmOpcode::FDIV => "FDIV", + AvmOpcode::ADD_8 => "ADD_8", + AvmOpcode::ADD_16 => "ADD_16", + AvmOpcode::SUB_8 => "SUB_8", + AvmOpcode::SUB_16 => "SUB_16", + AvmOpcode::MUL_8 => "MUL_8", + AvmOpcode::MUL_16 => "MUL_16", + AvmOpcode::DIV_8 => "DIV_8", + AvmOpcode::DIV_16 => "DIV_16", + AvmOpcode::FDIV_8 => "FDIV_8", + AvmOpcode::FDIV_16 => "FDIV_16", // Compute - Comparators - AvmOpcode::EQ => "EQ", - AvmOpcode::LT => "LT", - AvmOpcode::LTE => "LTE", + AvmOpcode::EQ_8 => "EQ_8", + AvmOpcode::EQ_16 => "EQ_16", + AvmOpcode::LT_8 => "LT_8", + AvmOpcode::LT_16 => "LT_16", + AvmOpcode::LTE_8 => "LTE_8", + AvmOpcode::LTE_16 => "LTE_16", // Compute - Bitwise - AvmOpcode::AND => "AND", - AvmOpcode::OR => "OR", - AvmOpcode::XOR => "XOR", + AvmOpcode::AND_8 => "AND_8", + AvmOpcode::AND_16 => "AND_16", + AvmOpcode::OR_8 => "OR_8", + AvmOpcode::OR_16 => "OR_16", + AvmOpcode::XOR_8 => "XOR_8", + AvmOpcode::XOR_16 => "XOR_16", AvmOpcode::NOT => "NOT", - AvmOpcode::SHL => "SHL", - AvmOpcode::SHR => "SHR", + AvmOpcode::SHL_8 => "SHL_8", + AvmOpcode::SHL_16 => "SHL_16", + AvmOpcode::SHR_8 => "SHR_8", + AvmOpcode::SHR_16 => "SHR_16", // Compute - Type Conversions AvmOpcode::CAST => "CAST", @@ -116,11 +145,8 @@ impl AvmOpcode { AvmOpcode::VERSION => "VERSION", AvmOpcode::BLOCKNUMBER => "BLOCKNUMBER", AvmOpcode::TIMESTAMP => "TIMESTAMP", - AvmOpcode::COINBASE => "COINBASE", AvmOpcode::FEEPERL2GAS => "FEEPERL2GAS", AvmOpcode::FEEPERDAGAS => "FEEPERDAGAS", - AvmOpcode::BLOCKL2GASLIMIT => "BLOCKL2GASLIMIT", - AvmOpcode::BLOCKDAGASLIMIT => "BLOCKDAGASLIMIT", // Execution Environment - Calldata AvmOpcode::CALLDATACOPY => "CALLDATACOPY", @@ -129,13 +155,19 @@ impl AvmOpcode { AvmOpcode::L2GASLEFT => "L2GASLEFT", AvmOpcode::DAGASLEFT => "DAGASLEFT", // Machine State - Internal Control Flow - AvmOpcode::JUMP => "JUMP", - AvmOpcode::JUMPI => "JUMPI", + AvmOpcode::JUMP_16 => "JUMP_16", + AvmOpcode::JUMPI_16 => "JUMPI_16", AvmOpcode::INTERNALCALL => "INTERNALCALL", AvmOpcode::INTERNALRETURN => "INTERNALRETURN", // Machine State - Memory - AvmOpcode::SET => "SET", - AvmOpcode::MOV => "MOV", + AvmOpcode::SET_8 => "SET_8", + AvmOpcode::SET_16 => "SET_16", + AvmOpcode::SET_32 => "SET_32", + AvmOpcode::SET_64 => "SET_64", + AvmOpcode::SET_128 => "SET_128", + AvmOpcode::SET_FF => "SET_FF", + AvmOpcode::MOV_8 => "MOV_8", + AvmOpcode::MOV_16 => "MOV_16", AvmOpcode::CMOV => "CMOV", // World State diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index db143469536..23c3e9fbc94 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -6,15 +6,16 @@ use acvm::acir::circuit::BrilligOpcodeLocation; use acvm::brillig_vm::brillig::{ BinaryFieldOp, BinaryIntOp, BlackBoxOp, HeapArray, HeapVector, MemoryAddress, ValueOrArray, }; -use acvm::{AcirField, FieldElement}; +use acvm::FieldElement; use noirc_errors::debug_info::DebugInfo; +use crate::bit_traits::bits_needed_for; use crate::instructions::{ AvmInstruction, AvmOperand, AvmTypeTag, ALL_DIRECT, FIRST_OPERAND_INDIRECT, SECOND_OPERAND_INDIRECT, ZEROTH_OPERAND_INDIRECT, }; use crate::opcodes::AvmOpcode; -use crate::utils::{dbg_print_avm_program, dbg_print_brillig_program}; +use crate::utils::{dbg_print_avm_program, dbg_print_brillig_program, make_operand}; /// Transpile a Brillig program to AVM bytecode pub fn brillig_to_avm( @@ -29,24 +30,65 @@ pub fn brillig_to_avm( for brillig_instr in brillig_bytecode { match brillig_instr { BrilligOpcode::BinaryFieldOp { destination, op, lhs, rhs } => { + let bits_needed = + [lhs.0, rhs.0, destination.0].iter().map(bits_needed_for).max().unwrap(); + + assert!( + bits_needed == 8 || bits_needed == 16, + "BinaryFieldOp only support 8 or 16 bit encodings, got: {}", + bits_needed + ); + let avm_opcode = match op { - BinaryFieldOp::Add => AvmOpcode::ADD, - BinaryFieldOp::Sub => AvmOpcode::SUB, - BinaryFieldOp::Mul => AvmOpcode::MUL, - BinaryFieldOp::Div => AvmOpcode::FDIV, - BinaryFieldOp::IntegerDiv => AvmOpcode::DIV, - BinaryFieldOp::Equals => AvmOpcode::EQ, - BinaryFieldOp::LessThan => AvmOpcode::LT, - BinaryFieldOp::LessThanEquals => AvmOpcode::LTE, + BinaryFieldOp::Add => match bits_needed { + 8 => AvmOpcode::ADD_8, + 16 => AvmOpcode::ADD_16, + _ => unreachable!(), + }, + BinaryFieldOp::Sub => match bits_needed { + 8 => AvmOpcode::SUB_8, + 16 => AvmOpcode::SUB_16, + _ => unreachable!(), + }, + BinaryFieldOp::Mul => match bits_needed { + 8 => AvmOpcode::MUL_8, + 16 => AvmOpcode::MUL_16, + _ => unreachable!(), + }, + BinaryFieldOp::Div => match bits_needed { + 8 => AvmOpcode::FDIV_8, + 16 => AvmOpcode::FDIV_16, + _ => unreachable!(), + }, + BinaryFieldOp::IntegerDiv => match bits_needed { + 8 => AvmOpcode::DIV_8, + 16 => AvmOpcode::DIV_16, + _ => unreachable!(), + }, + BinaryFieldOp::Equals => match bits_needed { + 8 => AvmOpcode::EQ_8, + 16 => AvmOpcode::EQ_16, + _ => unreachable!(), + }, + BinaryFieldOp::LessThan => match bits_needed { + 8 => AvmOpcode::LT_8, + 16 => AvmOpcode::LT_16, + _ => unreachable!(), + }, + BinaryFieldOp::LessThanEquals => match bits_needed { + 8 => AvmOpcode::LTE_8, + 16 => AvmOpcode::LTE_16, + _ => unreachable!(), + }, }; avm_instrs.push(AvmInstruction { opcode: avm_opcode, indirect: Some(ALL_DIRECT), - tag: if avm_opcode == AvmOpcode::FDIV { None } else { Some(AvmTypeTag::FIELD) }, + tag: Some(AvmTypeTag::FIELD), operands: vec![ - AvmOperand::U32 { value: lhs.to_usize() as u32 }, - AvmOperand::U32 { value: rhs.to_usize() as u32 }, - AvmOperand::U32 { value: destination.to_usize() as u32 }, + make_operand(bits_needed, &lhs.0), + make_operand(bits_needed, &rhs.0), + make_operand(bits_needed, &destination.0), ], }); } @@ -56,40 +98,96 @@ pub fn brillig_to_avm( "BinaryIntOp bit size should be integral: {:?}", brillig_instr ); + let bits_needed = + [lhs.0, rhs.0, destination.0].iter().map(bits_needed_for).max().unwrap(); + assert!( + bits_needed == 8 || bits_needed == 16, + "BinaryIntOp only support 8 or 16 bit encodings, got: {}", + bits_needed + ); + let avm_opcode = match op { - BinaryIntOp::Add => AvmOpcode::ADD, - BinaryIntOp::Sub => AvmOpcode::SUB, - BinaryIntOp::Mul => AvmOpcode::MUL, - BinaryIntOp::Div => AvmOpcode::DIV, - BinaryIntOp::Equals => AvmOpcode::EQ, - BinaryIntOp::LessThan => AvmOpcode::LT, - BinaryIntOp::LessThanEquals => AvmOpcode::LTE, - BinaryIntOp::And => AvmOpcode::AND, - BinaryIntOp::Or => AvmOpcode::OR, - BinaryIntOp::Xor => AvmOpcode::XOR, - BinaryIntOp::Shl => AvmOpcode::SHL, - BinaryIntOp::Shr => AvmOpcode::SHR, + BinaryIntOp::Add => match bits_needed { + 8 => AvmOpcode::ADD_8, + 16 => AvmOpcode::ADD_16, + _ => unreachable!(), + }, + BinaryIntOp::Sub => match bits_needed { + 8 => AvmOpcode::SUB_8, + 16 => AvmOpcode::SUB_16, + _ => unreachable!(), + }, + BinaryIntOp::Mul => match bits_needed { + 8 => AvmOpcode::MUL_8, + 16 => AvmOpcode::MUL_16, + _ => unreachable!(), + }, + BinaryIntOp::Div => match bits_needed { + 8 => AvmOpcode::DIV_8, + 16 => AvmOpcode::DIV_16, + _ => unreachable!(), + }, + BinaryIntOp::And => match bits_needed { + 8 => AvmOpcode::AND_8, + 16 => AvmOpcode::AND_16, + _ => unreachable!(), + }, + BinaryIntOp::Or => match bits_needed { + 8 => AvmOpcode::OR_8, + 16 => AvmOpcode::OR_16, + _ => unreachable!(), + }, + BinaryIntOp::Xor => match bits_needed { + 8 => AvmOpcode::XOR_8, + 16 => AvmOpcode::XOR_16, + _ => unreachable!(), + }, + BinaryIntOp::Shl => match bits_needed { + 8 => AvmOpcode::SHL_8, + 16 => AvmOpcode::SHL_16, + _ => unreachable!(), + }, + BinaryIntOp::Shr => match bits_needed { + 8 => AvmOpcode::SHR_8, + 16 => AvmOpcode::SHR_16, + _ => unreachable!(), + }, + BinaryIntOp::Equals => match bits_needed { + 8 => AvmOpcode::EQ_8, + 16 => AvmOpcode::EQ_16, + _ => unreachable!(), + }, + BinaryIntOp::LessThan => match bits_needed { + 8 => AvmOpcode::LT_8, + 16 => AvmOpcode::LT_16, + _ => unreachable!(), + }, + BinaryIntOp::LessThanEquals => match bits_needed { + 8 => AvmOpcode::LTE_8, + 16 => AvmOpcode::LTE_16, + _ => unreachable!(), + }, }; avm_instrs.push(AvmInstruction { opcode: avm_opcode, indirect: Some(ALL_DIRECT), tag: Some(tag_from_bit_size(BitSize::Integer(*bit_size))), operands: vec![ - AvmOperand::U32 { value: lhs.to_usize() as u32 }, - AvmOperand::U32 { value: rhs.to_usize() as u32 }, - AvmOperand::U32 { value: destination.to_usize() as u32 }, + make_operand(bits_needed, &lhs.0), + make_operand(bits_needed, &rhs.0), + make_operand(bits_needed, &destination.0), ], }); } - BrilligOpcode::CalldataCopy { destination_address, size, offset } => { + BrilligOpcode::CalldataCopy { destination_address, size_address, offset_address } => { avm_instrs.push(AvmInstruction { opcode: AvmOpcode::CALLDATACOPY, indirect: Some(ALL_DIRECT), operands: vec![ AvmOperand::U32 { - value: *offset as u32, // cdOffset (calldata offset) + value: offset_address.to_usize() as u32, // cdOffset (calldata offset) }, - AvmOperand::U32 { value: *size as u32 }, + AvmOperand::U32 { value: size_address.to_usize() as u32 }, // sizeOffset AvmOperand::U32 { value: destination_address.to_usize() as u32, // dstOffset }, @@ -100,20 +198,17 @@ pub fn brillig_to_avm( BrilligOpcode::Jump { location } => { let avm_loc = brillig_pcs_to_avm_pcs[*location]; avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::JUMP, - operands: vec![AvmOperand::U32 { value: avm_loc as u32 }], + opcode: AvmOpcode::JUMP_16, + operands: vec![make_operand(16, &avm_loc)], ..Default::default() }); } BrilligOpcode::JumpIf { condition, location } => { let avm_loc = brillig_pcs_to_avm_pcs[*location]; avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::JUMPI, + opcode: AvmOpcode::JUMPI_16, indirect: Some(ALL_DIRECT), - operands: vec![ - AvmOperand::U32 { value: avm_loc as u32 }, - AvmOperand::U32 { value: condition.to_usize() as u32 }, - ], + operands: vec![make_operand(16, &avm_loc), make_operand(16, &condition.0)], ..Default::default() }); } @@ -216,9 +311,9 @@ pub fn brillig_to_avm( // We are adding a MOV instruction that moves a value to itself. // This should therefore not affect the program's execution. avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::MOV, + opcode: AvmOpcode::MOV_16, indirect: Some(ALL_DIRECT), - operands: vec![AvmOperand::U32 { value: 0x18ca }, AvmOperand::U32 { value: 0x18ca }], + operands: vec![AvmOperand::U16 { value: 0x18ca }, AvmOperand::U16 { value: 0x18ca }], ..Default::default() }); @@ -265,6 +360,7 @@ fn handle_foreign_call( "avmOpcodeGetContractInstance" => { handle_get_contract_instance(avm_instrs, destinations, inputs); } + "avmOpcodeCalldataCopy" => handle_calldata_copy(avm_instrs, destinations, inputs), "avmOpcodeStorageRead" => handle_storage_read(avm_instrs, destinations, inputs), "avmOpcodeStorageWrite" => handle_storage_write(avm_instrs, destinations, inputs), "debugLog" => handle_debug_log(avm_instrs, destinations, inputs), @@ -673,45 +769,38 @@ fn handle_const( ) { let tag = tag_from_bit_size(*bit_size); let dest = destination.to_usize() as u32; - - if !matches!(tag, AvmTypeTag::FIELD) { - avm_instrs.push(generate_set_instruction(tag, dest, value.to_u128(), indirect)); - } else { - // We can't fit a field in an instruction. This should've been handled in Brillig. - let field = value; - if field.num_bits() > 128 { - panic!("SET: Field value doesn't fit in 128 bits, that's not supported!"); - } - avm_instrs.extend([ - generate_set_instruction(AvmTypeTag::UINT128, dest, field.to_u128(), indirect), - generate_cast_instruction(dest, indirect, dest, indirect, AvmTypeTag::FIELD), - ]); - } + avm_instrs.push(generate_set_instruction(tag, dest, value, indirect)); } /// Generates an AVM SET instruction. fn generate_set_instruction( tag: AvmTypeTag, dest: u32, - value: u128, + value: &FieldElement, indirect: bool, ) -> AvmInstruction { + let bits_needed_val = bits_needed_for(value); + let bits_needed_mem = if bits_needed_val >= 16 { 16 } else { bits_needed_for(&dest) }; + assert!(bits_needed_mem <= 16); + let bits_needed_opcode = bits_needed_val.max(bits_needed_mem); + + let set_opcode = match bits_needed_opcode { + 8 => AvmOpcode::SET_8, + 16 => AvmOpcode::SET_16, + 32 => AvmOpcode::SET_32, + 64 => AvmOpcode::SET_64, + 128 => AvmOpcode::SET_128, + 254 => AvmOpcode::SET_FF, + _ => panic!("Invalid bits needed for opcode: {}", bits_needed_opcode), + }; + AvmInstruction { - opcode: AvmOpcode::SET, + opcode: set_opcode, indirect: if indirect { Some(ZEROTH_OPERAND_INDIRECT) } else { Some(ALL_DIRECT) }, tag: Some(tag), operands: vec![ - // const - match tag { - AvmTypeTag::UINT8 => AvmOperand::U8 { value: value as u8 }, - AvmTypeTag::UINT16 => AvmOperand::U16 { value: value as u16 }, - AvmTypeTag::UINT32 => AvmOperand::U32 { value: value as u32 }, - AvmTypeTag::UINT64 => AvmOperand::U64 { value: value as u64 }, - AvmTypeTag::UINT128 => AvmOperand::U128 { value }, - _ => panic!("Invalid type tag {:?} for set", tag), - }, - // dest offset - AvmOperand::U32 { value: dest }, + make_operand(bits_needed_opcode, value), + make_operand(bits_needed_mem, &dest), ], } } @@ -741,10 +830,18 @@ fn generate_cast_instruction( /// Generates an AVM MOV instruction. fn generate_mov_instruction(indirect: Option, source: u32, dest: u32) -> AvmInstruction { + let bits_needed = [source, dest].iter().map(bits_needed_for).max().unwrap(); + + let mov_opcode = match bits_needed { + 8 => AvmOpcode::MOV_8, + 16 => AvmOpcode::MOV_16, + _ => panic!("MOV operands must fit in 16 bits but needed {}", bits_needed), + }; + AvmInstruction { - opcode: AvmOpcode::MOV, + opcode: mov_opcode, indirect, - operands: vec![AvmOperand::U32 { value: source }, AvmOperand::U32 { value: dest }], + operands: vec![make_operand(bits_needed, &source), make_operand(bits_needed, &dest)], ..Default::default() } } @@ -974,6 +1071,47 @@ fn handle_debug_log( }); } +// #[oracle(avmOpcodeCalldataCopy)] +// unconstrained fn calldata_copy_opcode(cdoffset: Field) -> [Field; N] {} +fn handle_calldata_copy( + avm_instrs: &mut Vec, + destinations: &Vec, + inputs: &Vec, +) { + assert!(inputs.len() == 2); + assert!(destinations.len() == 1); + + let cd_offset = match inputs[0] { + ValueOrArray::MemoryAddress(address) => address.0, + _ => panic!("CalldataCopy offset should be a memory address"), + }; + + let copy_size_offset = match inputs[1] { + ValueOrArray::MemoryAddress(address) => address.0, + _ => panic!("CalldataCopy size should be a memory address"), + }; + + let (dest_offset, ..) = match destinations[0] { + ValueOrArray::HeapArray(HeapArray { pointer, size }) => (pointer.0, size), + _ => panic!("CalldataCopy destination should be an array"), + }; + + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::CALLDATACOPY, + indirect: Some(SECOND_OPERAND_INDIRECT), + operands: vec![ + AvmOperand::U32 { + value: cd_offset as u32, // cdOffset (calldata offset) + }, + AvmOperand::U32 { value: copy_size_offset as u32 }, // copy size + AvmOperand::U32 { + value: dest_offset as u32, // dstOffset + }, + ], + ..Default::default() + }); +} + /// Emit a storage write opcode /// The current implementation writes an array of values into storage ( contiguous slots in memory ) fn handle_storage_write( @@ -1128,8 +1266,6 @@ pub fn map_brillig_pcs_to_avm_pcs(brillig_bytecode: &[BrilligOpcode 2, - BrilligOpcode::IndirectConst { bit_size: BitSize::Field, .. } => 2, BrilligOpcode::Cast { bit_size: BitSize::Integer(IntegerBitSize::U1), .. } => 3, _ => 1, }; diff --git a/avm-transpiler/src/transpile_contract.rs b/avm-transpiler/src/transpile_contract.rs index e684a541d84..fff7ad27522 100644 --- a/avm-transpiler/src/transpile_contract.rs +++ b/avm-transpiler/src/transpile_contract.rs @@ -100,6 +100,7 @@ impl From for TranspiledContractArtifact { let acir_program = function.bytecode; let brillig_bytecode = extract_brillig_from_acir_program(&acir_program); let assert_messages = extract_static_assert_messages(&acir_program); + info!("Extracted Brillig program has {} instructions", brillig_bytecode.len()); // Map Brillig pcs to AVM pcs (index is Brillig PC, value is AVM PC) let brillig_pcs_to_avm_pcs = map_brillig_pcs_to_avm_pcs(brillig_bytecode); @@ -118,7 +119,7 @@ impl From for TranspiledContractArtifact { let _ = encoder.read_to_end(&mut compressed_avm_bytecode); log::info!( - "{}::{}: compressed {} to {} bytes ({}% reduction)", + "{}::{}: bytecode size of {} was compressed to {} ({}% reduction)", contract.name, function.name, avm_bytecode.len(), diff --git a/avm-transpiler/src/utils.rs b/avm-transpiler/src/utils.rs index 19f9468e15c..3f5269f5daa 100644 --- a/avm-transpiler/src/utils.rs +++ b/avm-transpiler/src/utils.rs @@ -1,13 +1,14 @@ use fxhash::FxHashMap as HashMap; use acvm::acir::circuit::brillig::BrilligFunctionId; -use acvm::FieldElement; -use log::debug; +use acvm::{AcirField, FieldElement}; +use log::{debug, info, trace}; use acvm::acir::brillig::Opcode as BrilligOpcode; use acvm::acir::circuit::{AssertionPayload, Opcode, Program}; -use crate::instructions::AvmInstruction; +use crate::instructions::{AvmInstruction, AvmOperand}; +use crate::opcodes::AvmOpcode; /// Extract the Brillig program from its `Program` wrapper. /// Noir entry point unconstrained functions are compiled to their own list contained @@ -67,16 +68,38 @@ pub fn extract_static_assert_messages(program: &Program) -> HashMa /// Print inputs, outputs, and instructions in a Brillig program pub fn dbg_print_brillig_program(brillig_bytecode: &[BrilligOpcode]) { - debug!("Printing Brillig program..."); + trace!("Printing Brillig program..."); for (i, instruction) in brillig_bytecode.iter().enumerate() { - debug!("\tPC:{0} {1:?}", i, instruction); + trace!("\tPC:{0} {1:?}", i, instruction); } } /// Print each instruction in an AVM program pub fn dbg_print_avm_program(avm_program: &[AvmInstruction]) { - debug!("Printing AVM program..."); + info!("Transpiled AVM program has {} instructions", avm_program.len()); + trace!("Printing AVM program..."); + let mut counts = std::collections::HashMap::::new(); for (i, instruction) in avm_program.iter().enumerate() { - debug!("\tPC:{0}: {1}", i, &instruction.to_string()); + trace!("\tPC:{0}: {1}", i, &instruction.to_string()); + *counts.entry(instruction.opcode).or_insert(0) += 1; + } + debug!("AVM opcode counts:"); + let mut sorted_counts: Vec<_> = counts.into_iter().collect(); + sorted_counts.sort_by_key(|(_, count)| -(*count as isize)); + for (opcode, count) in sorted_counts { + debug!("\t{0:?}: {1}", opcode, count); + } +} + +pub fn make_operand + Clone>(bits: usize, value: &T) -> AvmOperand { + let field: FieldElement = value.clone().into(); + match bits { + 8 => AvmOperand::U8 { value: field.try_to_u32().unwrap() as u8 }, + 16 => AvmOperand::U16 { value: field.try_to_u32().unwrap() as u16 }, + 32 => AvmOperand::U32 { value: field.try_to_u32().unwrap() }, + 64 => AvmOperand::U64 { value: field.try_to_u64().unwrap() }, + 128 => AvmOperand::U128 { value: field.try_into_u128().unwrap() }, + 254 => AvmOperand::FF { value: field }, + _ => panic!("Invalid operand size for bits: {}", bits), } } diff --git a/aztec-up/README.md b/aztec-up/README.md index 4a8ebf22fa2..e46bfbceaec 100644 --- a/aztec-up/README.md +++ b/aztec-up/README.md @@ -1,7 +1,7 @@ # The Aztec Installation Script ``` -bash -i <(curl -s install.aztec.network) +bash -i <(curl -s https://install.aztec.network) ``` That is all. diff --git a/aztec-up/bin/aztec-up b/aztec-up/bin/aztec-up index 6f86c093fa8..7e718a33dab 100755 --- a/aztec-up/bin/aztec-up +++ b/aztec-up/bin/aztec-up @@ -3,4 +3,4 @@ set -euo pipefail export VERSION=${1:-${VERSION:-}} export NON_INTERACTIVE=1 -bash -i <(curl -s http://install.aztec.network) +bash -i <(curl -s https://install.aztec.network) diff --git a/aztec-up/terraform/main.tf b/aztec-up/terraform/main.tf index 2465082e3fa..4177d0ff285 100644 --- a/aztec-up/terraform/main.tf +++ b/aztec-up/terraform/main.tf @@ -75,14 +75,81 @@ resource "null_resource" "upload_public_directory" { } } -resource "aws_route53_record" "subdomain_record" { +# resource "aws_route53_record" "subdomain_record" { +# zone_id = data.terraform_remote_state.aztec2_iac.outputs.aws_route53_zone_id +# name = "install.aztec.network" +# type = "A" + +# alias { +# name = aws_s3_bucket_website_configuration.website_bucket.website_domain +# zone_id = aws_s3_bucket.install_bucket.hosted_zone_id +# evaluate_target_health = true +# } +# } + +resource "aws_cloudfront_distribution" "install" { + origin { + domain_name = aws_s3_bucket.install_bucket.website_endpoint + origin_id = "S3-install-aztec-network" + + custom_origin_config { + http_port = 80 + https_port = 443 + origin_protocol_policy = "http-only" + origin_ssl_protocols = ["TLSv1.2"] + } + } + + enabled = true + is_ipv6_enabled = true + default_root_object = "" + + aliases = ["install.aztec.network"] + + default_cache_behavior { + allowed_methods = ["GET", "HEAD"] + cached_methods = ["GET", "HEAD"] + target_origin_id = "S3-install-aztec-network" + + forwarded_values { + query_string = false + + cookies { + forward = "none" + } + } + + # TODO: Once new aztec-up script (almost certainly within days of this change), switch to redirect-to-https. + # viewer_protocol_policy = "redirect-to-https" + viewer_protocol_policy = "allow-all" + min_ttl = 0 + default_ttl = 3600 + max_ttl = 86400 + } + + price_class = "PriceClass_All" + + viewer_certificate { + acm_certificate_arn = data.terraform_remote_state.aztec2_iac.outputs.aws_acm_certificate_aztec_network_arn + ssl_support_method = "sni-only" + minimum_protocol_version = "TLSv1.2_2019" + } + + restrictions { + geo_restriction { + restriction_type = "none" + } + } +} + +resource "aws_route53_record" "install_record" { zone_id = data.terraform_remote_state.aztec2_iac.outputs.aws_route53_zone_id name = "install.aztec.network" type = "A" alias { - name = "${aws_s3_bucket_website_configuration.website_bucket.website_domain}" - zone_id = "${aws_s3_bucket.install_bucket.hosted_zone_id}" - evaluate_target_health = true + name = aws_cloudfront_distribution.install.domain_name + zone_id = aws_cloudfront_distribution.install.hosted_zone_id + evaluate_target_health = false } } diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index 85c9e0a5eb0..1c7bba2251c 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = 5c80b2b96beab914a7d443310db06e2fb50c1bcd - parent = f1746999ea12cc8117efd5a0c3b2ec5d80196343 + commit = c51bd8fa77d04c01099948434a18e142093f49ee + parent = 11dc8ff185d74e6e5bc51e85d6bcd6577ac83161 method = merge cmdver = 0.4.6 diff --git a/barretenberg/CHANGELOG.md b/barretenberg/CHANGELOG.md index 83759da8009..6a798b08f6d 100644 --- a/barretenberg/CHANGELOG.md +++ b/barretenberg/CHANGELOG.md @@ -1,5 +1,76 @@ # Changelog +## [0.54.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.53.0...barretenberg-v0.54.0) (2024-09-10) + + +### ⚠ BREAKING CHANGES + +* **avm:** variants for binary operations ([#8473](https://github.com/AztecProtocol/aztec-packages/issues/8473)) +* **avm:** make JUMP(I) 16-bit ([#8443](https://github.com/AztecProtocol/aztec-packages/issues/8443)) +* **avm:** variants for SET opcode ([#8441](https://github.com/AztecProtocol/aztec-packages/issues/8441)) +* **avm:** variants for MOV opcode ([#8440](https://github.com/AztecProtocol/aztec-packages/issues/8440)) + +### Features + +* (bb) 128-bit challenges ([#8406](https://github.com/AztecProtocol/aztec-packages/issues/8406)) ([d5b2397](https://github.com/AztecProtocol/aztec-packages/commit/d5b239745178d1ce4eb8b8d32fa4b366c13c3c94)) +* **avm:** DSL integration of AVM recursive verifier ([#8405](https://github.com/AztecProtocol/aztec-packages/issues/8405)) ([467120e](https://github.com/AztecProtocol/aztec-packages/commit/467120e5a95de267910c2f95b65dcb62c60f995d)), closes [#8285](https://github.com/AztecProtocol/aztec-packages/issues/8285) +* **avm:** Make JUMP(I) 16-bit ([#8443](https://github.com/AztecProtocol/aztec-packages/issues/8443)) ([5bb38b1](https://github.com/AztecProtocol/aztec-packages/commit/5bb38b1692469520f29a1c85bc381c1ca9eb4032)) +* **avm:** Variants for binary operations ([#8473](https://github.com/AztecProtocol/aztec-packages/issues/8473)) ([8de1f2a](https://github.com/AztecProtocol/aztec-packages/commit/8de1f2a942024aad955ea0f318cb044e3692b7fc)) +* **avm:** Variants for MOV opcode ([#8440](https://github.com/AztecProtocol/aztec-packages/issues/8440)) ([5b27fbc](https://github.com/AztecProtocol/aztec-packages/commit/5b27fbca982442251a350d6571bdd007b715d575)) +* **avm:** Variants for SET opcode ([#8441](https://github.com/AztecProtocol/aztec-packages/issues/8441)) ([dc43306](https://github.com/AztecProtocol/aztec-packages/commit/dc433064391b2ac93bca6b838adac271fbd28991)) +* **bb:** Towards reduced polynomial memory usage ([#7990](https://github.com/AztecProtocol/aztec-packages/issues/7990)) ([372f23c](https://github.com/AztecProtocol/aztec-packages/commit/372f23ce0aa44a3aa6e1ef2f864df303a3229e6b)) + + +### Bug Fixes + +* **avm:** Full proving kernel fix ([#8468](https://github.com/AztecProtocol/aztec-packages/issues/8468)) ([684d962](https://github.com/AztecProtocol/aztec-packages/commit/684d96271669116380facfa48db6cba3a5d945de)) +* **bb:** Mac release ([#8450](https://github.com/AztecProtocol/aztec-packages/issues/8450)) ([1b3f914](https://github.com/AztecProtocol/aztec-packages/commit/1b3f914fc069ec84fbd93621eb369128c3ba0dc5)) + + +### Miscellaneous + +* **bb:** Remove poly downsizing, other fast-follow from structured polys ([#8475](https://github.com/AztecProtocol/aztec-packages/issues/8475)) ([ac88f30](https://github.com/AztecProtocol/aztec-packages/commit/ac88f30808199c2625f889671f2767c3667becb5)) +* Rename files relating to what were "instances" ([#8383](https://github.com/AztecProtocol/aztec-packages/issues/8383)) ([a934e85](https://github.com/AztecProtocol/aztec-packages/commit/a934e85b416a029ae057e0e70277401fb7cfe4b9)) + +## [0.53.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.52.0...barretenberg-v0.53.0) (2024-09-09) + + +### ⚠ BREAKING CHANGES + +* **avm/brillig:** take addresses in calldatacopy ([#8388](https://github.com/AztecProtocol/aztec-packages/issues/8388)) +* remove coinbase and unimplemented block gas limit opcodes from AVM ([#8408](https://github.com/AztecProtocol/aztec-packages/issues/8408)) + +### Features + +* Add poseidon relations to UltraKeccak flavor and Solidity verifier ([#8243](https://github.com/AztecProtocol/aztec-packages/issues/8243)) ([f7e4bfb](https://github.com/AztecProtocol/aztec-packages/commit/f7e4bfb0fc8070b7b79366241f3d37357dfaee27)) +* **avm/brillig:** Take addresses in calldatacopy ([#8388](https://github.com/AztecProtocol/aztec-packages/issues/8388)) ([eab944c](https://github.com/AztecProtocol/aztec-packages/commit/eab944cbb77eb613e61a879312b58c415f8a0c13)) +* **ci:** Tracy gate counter preset ([#8382](https://github.com/AztecProtocol/aztec-packages/issues/8382)) ([882af1e](https://github.com/AztecProtocol/aztec-packages/commit/882af1ed821c135b68a5d693a81b7fc580ad97c2)) +* Replace arithmetic equalities with assert equal ([#8386](https://github.com/AztecProtocol/aztec-packages/issues/8386)) ([0d8e835](https://github.com/AztecProtocol/aztec-packages/commit/0d8e835dd6cd6cd545edda20f652ab6f10c530da)) +* Ultra keccak honk verifier ([#8261](https://github.com/AztecProtocol/aztec-packages/issues/8261)) ([7f02900](https://github.com/AztecProtocol/aztec-packages/commit/7f029007365b57c06699914f97b93d0891d2a6f1)) +* Update AztecIvc interface to facilitate acir-ivc ([#8230](https://github.com/AztecProtocol/aztec-packages/issues/8230)) ([665750a](https://github.com/AztecProtocol/aztec-packages/commit/665750a8d7f20ea4e3f7cded052b88eb6bb28600)) +* Verify public validation requests ([#8150](https://github.com/AztecProtocol/aztec-packages/issues/8150)) ([2be1415](https://github.com/AztecProtocol/aztec-packages/commit/2be14157abe3b277c58780ecc03bb1eff8dec20e)) + + +### Bug Fixes + +* Broken build ([#8395](https://github.com/AztecProtocol/aztec-packages/issues/8395)) ([d0ea6eb](https://github.com/AztecProtocol/aztec-packages/commit/d0ea6ebbe8b4bb918acc2aa5a4c09863a93b7c08)) +* Revert "feat: ultra keccak honk verifier ([#8427](https://github.com/AztecProtocol/aztec-packages/issues/8427)) ([31df5ea](https://github.com/AztecProtocol/aztec-packages/commit/31df5ead9e182bcf57588438f1b73eba4c052fa5)) +* Revert "feat: ultra keccak honk verifier" ([#8391](https://github.com/AztecProtocol/aztec-packages/issues/8391)) ([3228e75](https://github.com/AztecProtocol/aztec-packages/commit/3228e7526aa30b514375c62264cbde578754cd79)) + + +### Miscellaneous + +* **avm:** Move proving key to avm files ([#8318](https://github.com/AztecProtocol/aztec-packages/issues/8318)) ([32d67bd](https://github.com/AztecProtocol/aztec-packages/commit/32d67bd72244bfc3ea28aef7358c467a5b238b6b)) +* **avm:** Remove some unused deps ([#8366](https://github.com/AztecProtocol/aztec-packages/issues/8366)) ([e2150a7](https://github.com/AztecProtocol/aztec-packages/commit/e2150a7e5fc84932b65af07025514fc3c57f1cbc)) +* **bb:** Reinstate "chore: uncomment asserts in oink rec verifier"" ([#8356](https://github.com/AztecProtocol/aztec-packages/issues/8356)) ([4dbad01](https://github.com/AztecProtocol/aztec-packages/commit/4dbad01c866b28f7d440d7b4e17631ed6a0469f3)) +* **bb:** Use std::span for srs ([#8371](https://github.com/AztecProtocol/aztec-packages/issues/8371)) ([f174699](https://github.com/AztecProtocol/aztec-packages/commit/f1746999ea12cc8117efd5a0c3b2ec5d80196343)) +* Improve ec addition ([#8291](https://github.com/AztecProtocol/aztec-packages/issues/8291)) ([e8a097c](https://github.com/AztecProtocol/aztec-packages/commit/e8a097cf338bae2445006b3f20a2f54fc8f5e7f5)) +* More efficient verification with shplonk and gemini ([#8351](https://github.com/AztecProtocol/aztec-packages/issues/8351)) ([e51d157](https://github.com/AztecProtocol/aztec-packages/commit/e51d157fc7ae9a8ffeba8e6f89dbe87034d36db4)) +* Remove coinbase and unimplemented block gas limit opcodes from AVM ([#8408](https://github.com/AztecProtocol/aztec-packages/issues/8408)) ([dd09b76](https://github.com/AztecProtocol/aztec-packages/commit/dd09b76f70420a3824bf406bb2044481f68cd741)) +* Remove unimplemented headermember opcode from avm ([#8407](https://github.com/AztecProtocol/aztec-packages/issues/8407)) ([cfea06e](https://github.com/AztecProtocol/aztec-packages/commit/cfea06ed72449a62e21ba4b0f1b0d77200f91635)) +* Renaming `Instance`'s ([#8362](https://github.com/AztecProtocol/aztec-packages/issues/8362)) ([4789440](https://github.com/AztecProtocol/aztec-packages/commit/478944010ca8f28eabba733d04a9a8e9a43c29a9)) +* Uncomment asserts in oink rec verifier ([#8316](https://github.com/AztecProtocol/aztec-packages/issues/8316)) ([a7f3144](https://github.com/AztecProtocol/aztec-packages/commit/a7f314448215950f6f1a7d4f282359df040be502)) + ## [0.52.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.51.1...barretenberg-v0.52.0) (2024-09-01) diff --git a/barretenberg/acir_tests/flows/honk_sol.sh b/barretenberg/acir_tests/flows/honk_sol.sh index 1801d034e19..130380d76c3 100755 --- a/barretenberg/acir_tests/flows/honk_sol.sh +++ b/barretenberg/acir_tests/flows/honk_sol.sh @@ -19,7 +19,7 @@ export VERIFIER_PATH="$(pwd)/Verifier.sol" export TEST_PATH=$(realpath "../../sol-test/HonkTest.sol") export TESTING_HONK="true" -# Use solcjs to compile the generated key contract with the template verifier and test contract +# Use solcjs to compile the generated key contract with the template verifier and test contract # index.js will start an anvil, on a random port # Deploy the verifier then send a test transaction export TEST_NAME=$(basename $(pwd)) diff --git a/barretenberg/acir_tests/sol-test/src/index.js b/barretenberg/acir_tests/sol-test/src/index.js index 81833cd9e24..bcfed952892 100644 --- a/barretenberg/acir_tests/sol-test/src/index.js +++ b/barretenberg/acir_tests/sol-test/src/index.js @@ -3,9 +3,11 @@ const { readFileSync, promises: fsPromises } = fs; import { spawn } from "child_process"; import { ethers } from "ethers"; import solc from "solc"; +import linker from "solc/linker.js"; const NUMBER_OF_FIELDS_IN_PLONK_PROOF = 93; -const NUMBER_OF_FIELDS_IN_HONK_PROOF = 393; +// This excludes the public inputs which are sent separately to the Solidity verifier +const NUMBER_OF_FIELDS_IN_HONK_PROOF = 423; // We use the solcjs compiler version in this test, although it is slower than foundry, to run the test end to end // it simplifies of parallelising the test suite @@ -73,28 +75,26 @@ export const compilationInput = { // If testing honk is set, then we compile the honk test suite const testingHonk = getEnvVarCanBeUndefined("TESTING_HONK"); -const NUMBER_OF_FIELDS_IN_PROOF = testingHonk ? NUMBER_OF_FIELDS_IN_HONK_PROOF : NUMBER_OF_FIELDS_IN_PLONK_PROOF; +const NUMBER_OF_FIELDS_IN_PROOF = testingHonk + ? NUMBER_OF_FIELDS_IN_HONK_PROOF + : NUMBER_OF_FIELDS_IN_PLONK_PROOF; if (!testingHonk) { - - const keyPath = getEnvVar("KEY_PATH"); - const basePath = getEnvVar("BASE_PATH"); - const [key, base] = await Promise.all( - [ - fsPromises.readFile(keyPath, encoding), - fsPromises.readFile(basePath, encoding), - ] - ); - - compilationInput.sources["BaseUltraVerifier.sol"] = { - content: base, - }; - compilationInput.sources["Key.sol"] = { - content: key, - }; + const keyPath = getEnvVar("KEY_PATH"); + const basePath = getEnvVar("BASE_PATH"); + const [key, base] = await Promise.all([ + fsPromises.readFile(keyPath, encoding), + fsPromises.readFile(basePath, encoding), + ]); + + compilationInput.sources["BaseUltraVerifier.sol"] = { + content: base, + }; + compilationInput.sources["Key.sol"] = { + content: key, + }; } var output = JSON.parse(solc.compile(JSON.stringify(compilationInput))); - const contract = output.contracts["Test.sol"]["Test"]; const bytecode = contract.evm.bytecode.object; const abi = contract.abi; @@ -133,7 +133,7 @@ const launchAnvil = async (port) => { * Deploys the contract * @param {ethers.Signer} signer */ -const deploy = async (signer) => { +const deploy = async (signer, abi, bytecode) => { const factory = new ethers.ContractFactory(abi, bytecode, signer); const deployment = await factory.deploy(); const deployed = await deployment.waitForDeployment(); @@ -147,14 +147,14 @@ const deploy = async (signer) => { */ const readPublicInputs = (proofAsFields) => { const publicInputs = []; - // A proof with no public inputs is 93 fields long + // Compute the number of public inputs, not accounted for in the constant NUMBER_OF_FIELDS_IN_PROOF const numPublicInputs = proofAsFields.length - NUMBER_OF_FIELDS_IN_PROOF; let publicInputsOffset = 0; - + // Honk proofs contain 3 pieces of metadata before the public inputs, while plonk does not if (testingHonk) { publicInputsOffset = 3; - } + } for (let i = 0; i < numPublicInputs; i++) { publicInputs.push(proofAsFields[publicInputsOffset + i]); @@ -215,7 +215,7 @@ try { proofStr = proofStr.substring(8); // Get the part before and after the public inputs const proofStart = proofStr.slice(0, 64 * 3); - const proofEnd = proofStr.substring((64 * 3) + (64 * numPublicInputs)); + const proofEnd = proofStr.substring(64 * 3 + 64 * numPublicInputs); proofStr = proofStart + proofEnd; } else { proofStr = proofStr.substring(64 * numPublicInputs); @@ -228,8 +228,7 @@ try { const provider = await getProvider(randomPort); const signer = new ethers.Wallet(key, provider); - // deploy - const address = await deploy(signer); + const address = await deploy(signer, abi, bytecode); const contract = new ethers.Contract(address, abi, signer); const result = await contract.test(proofStr, publicInputs); diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index 1be0d115a87..e2caea121ac 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.24 FATAL_ERROR) project( Barretenberg DESCRIPTION "BN254 elliptic curve library, and PLONK SNARK prover" - VERSION 0.52.0 # x-release-please-version + VERSION 0.54.0 # x-release-please-version LANGUAGES CXX C ) # Insert version into `bb` config file diff --git a/barretenberg/cpp/pil/avm/constants_gen.pil b/barretenberg/cpp/pil/avm/constants_gen.pil index 9adc7a542c8..c2a17b1d7ec 100644 --- a/barretenberg/cpp/pil/avm/constants_gen.pil +++ b/barretenberg/cpp/pil/avm/constants_gen.pil @@ -20,7 +20,6 @@ namespace constants(256); pol VERSION_SELECTOR = 30; pol BLOCK_NUMBER_SELECTOR = 31; pol TIMESTAMP_SELECTOR = 33; - pol COINBASE_SELECTOR = 34; pol FEE_PER_DA_GAS_SELECTOR = 36; pol FEE_PER_L2_GAS_SELECTOR = 37; pol END_GLOBAL_VARIABLES = 38; diff --git a/barretenberg/cpp/pil/avm/kernel.pil b/barretenberg/cpp/pil/avm/kernel.pil index d04a5fa13ff..fce9aec35be 100644 --- a/barretenberg/cpp/pil/avm/kernel.pil +++ b/barretenberg/cpp/pil/avm/kernel.pil @@ -111,9 +111,6 @@ namespace main(256); #[TIMESTAMP_KERNEL] sel_op_timestamp * (kernel_in_offset - constants.TIMESTAMP_SELECTOR) = 0; - #[COINBASE_KERNEL] - sel_op_coinbase * (kernel_in_offset - constants.COINBASE_SELECTOR) = 0; - // CONTEXT - ENVIRONMENT - GLOBALS - FEES #[FEE_DA_GAS_KERNEL] sel_op_fee_per_da_gas * (kernel_in_offset - constants.FEE_PER_DA_GAS_SELECTOR) = 0; @@ -170,7 +167,7 @@ namespace main(256); //===== LOOKUPS INTO THE PUBLIC INPUTS =========================================== pol KERNEL_INPUT_SELECTORS = sel_op_address + sel_op_storage_address + sel_op_sender + sel_op_function_selector + sel_op_transaction_fee + sel_op_chain_id - + sel_op_version + sel_op_block_number + sel_op_coinbase + sel_op_timestamp + + sel_op_version + sel_op_block_number + sel_op_timestamp + sel_op_fee_per_l2_gas + sel_op_fee_per_da_gas; // Ensure that only one kernel lookup is active when the kernel_in_offset is active #[KERNEL_INPUT_ACTIVE_CHECK] diff --git a/barretenberg/cpp/pil/avm/main.pil b/barretenberg/cpp/pil/avm/main.pil index 198f6f6d8cb..b4debf47049 100644 --- a/barretenberg/cpp/pil/avm/main.pil +++ b/barretenberg/cpp/pil/avm/main.pil @@ -51,7 +51,6 @@ namespace main(256); pol commit sel_op_chain_id; pol commit sel_op_version; pol commit sel_op_block_number; - pol commit sel_op_coinbase; pol commit sel_op_timestamp; // CONTEXT - ENVIRONMENT - GLOBALS - FEES pol commit sel_op_fee_per_l2_gas; @@ -224,7 +223,6 @@ namespace main(256); sel_op_chain_id * (1 - sel_op_chain_id) = 0; sel_op_version * (1 - sel_op_version) = 0; sel_op_block_number * (1 - sel_op_block_number) = 0; - sel_op_coinbase * (1 - sel_op_coinbase) = 0; sel_op_timestamp * (1 - sel_op_timestamp) = 0; sel_op_fee_per_l2_gas * (1 - sel_op_fee_per_l2_gas) = 0; sel_op_fee_per_da_gas * (1 - sel_op_fee_per_da_gas) = 0; diff --git a/barretenberg/cpp/scripts/_benchmark_remote_lock.sh b/barretenberg/cpp/scripts/_benchmark_remote_lock.sh index 8ed0787051a..c9935a8ee62 100644 --- a/barretenberg/cpp/scripts/_benchmark_remote_lock.sh +++ b/barretenberg/cpp/scripts/_benchmark_remote_lock.sh @@ -1,6 +1,6 @@ # NOTE: This script is NOT meant to be ran, only sourced. # This sets up all the necessary machinery to lock ~/BENCHMARK_IN_PROGRESS -# +# # Function to clean up lock file function cleanup() { @@ -9,6 +9,13 @@ function cleanup() { } # Check for existing lock file +for i in {1..10} ; do + if ! ssh $BB_SSH_KEY $BB_SSH_INSTANCE "test -f ~/BENCHMARK_IN_PROGRESS"; then + break # we are able to benchmark + fi + echo "Benchmarking is already in progress. Waiting..." + sleep 10 # wait +done if ssh $BB_SSH_KEY $BB_SSH_INSTANCE "test -f ~/BENCHMARK_IN_PROGRESS"; then echo "Benchmarking is already in progress. If htop on the remote machine is not active, ~/BENCHMARK_IN_PROGRESS may need to be deleted." # Important: Exits the script that called this! diff --git a/barretenberg/cpp/src/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index a2c8ba9eb15..1a7a853b55b 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -103,7 +103,7 @@ include(GNUInstallDirs) message(STATUS "Compiling all-in-one barretenberg archive") set(BARRETENBERG_TARGET_OBJECTS - $ + $ $ $ $ diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp index 58df09e229e..d0817e8f7fe 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp @@ -4,67 +4,106 @@ namespace bb { /** - * @brief Append logic to complete a kernel circuit - * @details A kernel circuit may contain some combination of PG recursive verification, merge recursive verification, - * and databus commitment consistency checks. This method appends this logic to a provided kernel circuit. + * @brief Instantiate a stdlib verification queue for use in the kernel completion logic + * @details Construct a stdlib proof/verification_key for each entry in the native verification queue. By default, both + * are constructed from their counterpart in the native queue. Alternatively, Stdlib verification keys can be provided + * directly as input to this method. (The later option is used, for example, when constructing recursive verifiers based + * on the verification key witnesses from an acir recursion constraint. This option is not provided for proofs since + * valid proof witnesses are in general not known at the time of acir constraint generation). * * @param circuit */ -void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) +void AztecIVC::instantiate_stdlib_verification_queue( + ClientCircuit& circuit, const std::vector>& input_keys) { - circuit.databus_propagation_data.is_kernel = true; + bool vkeys_provided = !input_keys.empty(); + if (vkeys_provided && verification_queue.size() != input_keys.size()) { + info("Warning: Incorrect number of verification keys provided in stdlib verification queue instantiation."); + ASSERT(false); + } - // Perform recursive verification and databus consistency checks for each entry in the verification queue + size_t key_idx = 0; for (auto& [proof, vkey, type] : verification_queue) { - // Construct stdlib verification key and proof + // Construct stdlib proof directly from the internal native queue data auto stdlib_proof = bb::convert_proof_to_witness(&circuit, proof); - auto stdlib_vkey = std::make_shared(&circuit, vkey); - - switch (type) { - case QUEUE_TYPE::PG: { - // Construct stdlib verifier accumulator from the native counterpart computed on a previous round - auto stdlib_verifier_accum = - std::make_shared(&circuit, verifier_accumulator); - - // Perform folding recursive verification to update the verifier accumulator - FoldingRecursiveVerifier verifier{ &circuit, stdlib_verifier_accum, { stdlib_vkey } }; - auto verifier_accum = verifier.verify_folding_proof(stdlib_proof); - - // Extract native verifier accumulator from the stdlib accum for use on the next round - verifier_accumulator = std::make_shared(verifier_accum->get_value()); - - // Perform databus commitment consistency checks and propagate return data commitments via public inputs - bus_depot.execute(verifier.keys_to_fold[1]->witness_commitments, - verifier.keys_to_fold[1]->public_inputs, - verifier.keys_to_fold[1]->verification_key->databus_propagation_data); - break; - } - case QUEUE_TYPE::OINK: { - // Construct an incomplete stdlib verifier accumulator from the corresponding stdlib verification key - auto verifier_accum = std::make_shared(&circuit, stdlib_vkey); - - // Perform oink recursive verification to complete the initial verifier accumulator - OinkRecursiveVerifier oink{ &circuit, verifier_accum }; - oink.verify_proof(stdlib_proof); - verifier_accum->is_accumulator = true; // indicate to PG that it should not run oink on this key - - // Extract native verifier accumulator from the stdlib accum for use on the next round - verifier_accumulator = std::make_shared(verifier_accum->get_value()); - // Initialize the gate challenges to zero for use in first round of folding - verifier_accumulator->gate_challenges = - std::vector(verifier_accum->verification_key->log_circuit_size, 0); - - // Perform databus commitment consistency checks and propagate return data commitments via public inputs - bus_depot.execute(verifier_accum->witness_commitments, - verifier_accum->public_inputs, - verifier_accum->verification_key->databus_propagation_data); - - break; - } - } + + // Use the provided stdlib vkey if present, otherwise construct one from the internal native queue + auto stdlib_vkey = + vkeys_provided ? input_keys[key_idx++] : std::make_shared(&circuit, vkey); + + stdlib_verification_queue.push_back({ stdlib_proof, stdlib_vkey, type }); } - verification_queue.clear(); + verification_queue.clear(); // the native data is not needed beyond this point +} + +/** + * @brief Populate the provided circuit with constraints for (1) recursive verification of the provided accumulation + * proof and (2) the associated databus commitment consistency checks. + * @details The recursive verifier will be either Oink or Protogalaxy depending on the specified proof type. In either + * case, the verifier accumulator is updated in place via the verification algorithm. Databus commitment consistency + * checks are performed on the witness commitments and public inputs extracted from the proof by the verifier. + * + * @param circuit The circuit to which the constraints are appended + * @param proof A stdlib proof to be recursively verified (either oink or PG) + * @param vkey The stdlib verfication key associated with the proof + * @param type The type of the proof (equivalently, the type of the verifier) + */ +void AztecIVC::perform_recursive_verification_and_databus_consistency_checks( + ClientCircuit& circuit, + const StdlibProof& proof, + const std::shared_ptr& vkey, + const QUEUE_TYPE type) +{ + switch (type) { + case QUEUE_TYPE::PG: { + // Construct stdlib verifier accumulator from the native counterpart computed on a previous round + auto stdlib_verifier_accum = std::make_shared(&circuit, verifier_accumulator); + // Perform folding recursive verification to update the verifier accumulator + FoldingRecursiveVerifier verifier{ &circuit, stdlib_verifier_accum, { vkey } }; + auto verifier_accum = verifier.verify_folding_proof(proof); + + // Extract native verifier accumulator from the stdlib accum for use on the next round + verifier_accumulator = std::make_shared(verifier_accum->get_value()); + + // Perform databus commitment consistency checks and propagate return data commitments via public inputs + bus_depot.execute(verifier.keys_to_fold[1]->witness_commitments, + verifier.keys_to_fold[1]->public_inputs, + verifier.keys_to_fold[1]->verification_key->databus_propagation_data); + break; + } + case QUEUE_TYPE::OINK: { + // Construct an incomplete stdlib verifier accumulator from the corresponding stdlib verification key + auto verifier_accum = std::make_shared(&circuit, vkey); + + // Perform oink recursive verification to complete the initial verifier accumulator + OinkRecursiveVerifier oink{ &circuit, verifier_accum }; + oink.verify_proof(proof); + verifier_accum->is_accumulator = true; // indicate to PG that it should not run oink + + // Extract native verifier accumulator from the stdlib accum for use on the next round + verifier_accumulator = std::make_shared(verifier_accum->get_value()); + // Initialize the gate challenges to zero for use in first round of folding + auto log_circuit_size = static_cast(verifier_accum->verification_key->log_circuit_size); + verifier_accumulator->gate_challenges = std::vector(log_circuit_size, 0); + + // Perform databus commitment consistency checks and propagate return data commitments via public inputs + bus_depot.execute(verifier_accum->witness_commitments, + verifier_accum->public_inputs, + verifier_accum->verification_key->databus_propagation_data); + + break; + } + } +} + +/** + * @brief Perform recursive merge verification for each merge proof in the queue + * + * @param circuit + */ +void AztecIVC::process_recursive_merge_verification_queue(ClientCircuit& circuit) +{ // Recusively verify all merge proofs in queue for (auto& proof : merge_verification_queue) { goblin.verify_merge(circuit, proof); @@ -72,6 +111,33 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) merge_verification_queue.clear(); } +/** + * @brief Append logic to complete a kernel circuit + * @details A kernel circuit may contain some combination of PG recursive verification, merge recursive + * verification, and databus commitment consistency checks. This method appends this logic to a provided kernel + * circuit. + * + * @param circuit + */ +void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) +{ + circuit.databus_propagation_data.is_kernel = true; + + // Instantiate stdlib verifier inputs from their native counterparts + if (stdlib_verification_queue.empty()) { + instantiate_stdlib_verification_queue(circuit); + } + + // Peform recursive verification and databus consistency checks for each entry in the verification queue + for (auto& [proof, vkey, type] : stdlib_verification_queue) { + perform_recursive_verification_and_databus_consistency_checks(circuit, proof, vkey, type); + } + stdlib_verification_queue.clear(); + + // Perform recursive merge verification for every merge proof in the queue + process_recursive_merge_verification_queue(circuit); +} + /** * @brief Execute prover work for accumulation * @details Construct an proving key for the provided circuit. If this is the first step in the IVC, simply initialize @@ -115,7 +181,7 @@ void AztecIVC::accumulate(ClientCircuit& circuit, const std::shared_ptrproof_data, honk_vk, QUEUE_TYPE::OINK }); + bb::AztecIVC::VerifierInputs{ oink_prover.transcript->proof_data, honk_vk, QUEUE_TYPE::OINK }); initialized = true; } else { // Otherwise, fold the new key into the accumulator @@ -123,8 +189,7 @@ void AztecIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr>& vk_stack) +bool AztecIVC::verify(const Proof& proof, const std::vector>& vk_stack) { auto eccvm_vk = std::make_shared(goblin.get_eccvm_proving_key()); auto translator_vk = std::make_shared(goblin.get_translator_proving_key()); diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp index 2b07425f27e..29cf5f504de 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp @@ -6,7 +6,7 @@ #include "barretenberg/protogalaxy/protogalaxy_prover.hpp" #include "barretenberg/protogalaxy/protogalaxy_verifier.hpp" #include "barretenberg/stdlib/primitives/databus/databus.hpp" -#include "barretenberg/sumcheck/instance/instances.hpp" +#include "barretenberg/ultra_honk/decider_keys.hpp" #include "barretenberg/ultra_honk/decider_prover.hpp" #include "barretenberg/ultra_honk/decider_verifier.hpp" #include @@ -64,12 +64,23 @@ class AztecIVC { MSGPACK_FIELDS(folding_proof, decider_proof, goblin_proof); }; - enum class QUEUE_TYPE { OINK, PG }; - struct RecursiveVerifierInputs { + enum class QUEUE_TYPE { OINK, PG }; // for specifying type of proof in the verification queue + + // An entry in the native verification queue + struct VerifierInputs { std::vector proof; // oink or PG std::shared_ptr honk_verification_key; QUEUE_TYPE type; }; + using VerificationQueue = std::vector; + + // An entry in the stdlib verification queue + struct StdlibVerifierInputs { + StdlibProof proof; // oink or PG + std::shared_ptr honk_verification_key; + QUEUE_TYPE type; + }; + using StdlibVerificationQueue = std::vector; // Utility for tracking the max size of each block across the full IVC MaxBlockSizeTracker max_block_size_tracker; @@ -85,8 +96,10 @@ class AztecIVC { std::shared_ptr verifier_accumulator; // verifier accumulator std::shared_ptr honk_vk; // honk vk to be completed and folded into the accumulator - // Set of pairs of {fold_proof, verification_key} to be recursively verified - std::vector verification_queue; + // Set of tuples {proof, verification_key, type} to be recursively verified + VerificationQueue verification_queue; + // Set of tuples {stdlib_proof, stdlib_verification_key, type} corresponding to the native verification queue + StdlibVerificationQueue stdlib_verification_queue; // Set of merge proofs to be recursively verified std::vector merge_verification_queue; @@ -98,6 +111,17 @@ class AztecIVC { bool initialized = false; // Is the IVC accumulator initialized + void instantiate_stdlib_verification_queue( + ClientCircuit& circuit, const std::vector>& input_keys = {}); + + void perform_recursive_verification_and_databus_consistency_checks( + ClientCircuit& circuit, + const StdlibProof& proof, + const std::shared_ptr& vkey, + const QUEUE_TYPE type); + + void process_recursive_merge_verification_queue(ClientCircuit& circuit); + // Complete the logic of a kernel circuit (e.g. PG/merge recursive verification, databus consistency checks) void complete_kernel_circuit_logic(ClientCircuit& circuit); @@ -112,7 +136,7 @@ class AztecIVC { const std::shared_ptr& eccvm_vk, const std::shared_ptr& translator_vk); - bool verify(Proof& proof, const std::vector>& vk_stack); + bool verify(const Proof& proof, const std::vector>& vk_stack); bool prove_and_verify(); diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 9f69a7a8ac7..d318d9e337a 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -10,7 +10,7 @@ #include "barretenberg/serialize/cbind.hpp" #include "barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_keccak.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_keccak_flavor.hpp" #include #ifndef DISABLE_AZTEC_VM @@ -58,8 +58,10 @@ const auto current_dir = current_path.filename().string(); */ void init_bn254_crs(size_t dyadic_circuit_size) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1097): tighter bound needed + // currently using 1.6x points in CRS because of structured polys, see notes for how to minimize // Must +1 for Plonk only! - auto bn254_g1_data = get_bn254_g1_data(CRS_PATH, dyadic_circuit_size + 1); + auto bn254_g1_data = get_bn254_g1_data(CRS_PATH, dyadic_circuit_size + dyadic_circuit_size * 6 / 10 + 1); auto bn254_g2_data = get_bn254_g2_data(CRS_PATH); srs::init_crs_factory(bn254_g1_data, bn254_g2_data); } @@ -72,7 +74,10 @@ void init_bn254_crs(size_t dyadic_circuit_size) */ void init_grumpkin_crs(size_t eccvm_dyadic_circuit_size) { - auto grumpkin_g1_data = get_grumpkin_g1_data(CRS_PATH, eccvm_dyadic_circuit_size); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1097): tighter bound needed + // currently using 1.6x points in CRS because of structured polys, see notes for how to minimize + auto grumpkin_g1_data = + get_grumpkin_g1_data(CRS_PATH, eccvm_dyadic_circuit_size + eccvm_dyadic_circuit_size * 6 / 10); srs::init_grumpkin_crs_factory(grumpkin_g1_data); } @@ -951,12 +956,7 @@ void avm_prove(const std::filesystem::path& bytecode_path, auto const [verification_key, proof] = AVM_TRACK_TIME_V("prove/all", avm_trace::Execution::prove(bytecode, calldata, public_inputs_vec, avm_hints)); - std::vector vk_as_fields = { fr(verification_key.circuit_size), fr(verification_key.num_public_inputs) }; - - for (auto const& comm : verification_key.get_all()) { - std::vector comm_as_fields = field_conversion::convert_to_bn254_frs(comm); - vk_as_fields.insert(vk_as_fields.end(), comm_as_fields.begin(), comm_as_fields.end()); - } + std::vector vk_as_fields = verification_key.to_field_elements(); vinfo("vk fields size: ", vk_as_fields.size()); vinfo("circuit size: ", vk_as_fields[0]); @@ -1085,7 +1085,6 @@ void prove_honk(const std::string& bytecodePath, const std::string& witnessPath, // Construct Honk proof Prover prover = compute_valid_prover(bytecodePath, witnessPath); auto proof = prover.construct_proof(); - if (outputPath == "-") { writeRawBytesToStdout(to_buffer(proof)); vinfo("proof written to stdout"); @@ -1286,7 +1285,7 @@ void prove_honk_output_all(const std::string& bytecodePath, using VerificationKey = Flavor::VerificationKey; bool honk_recursion = false; - if constexpr (IsAnyOf) { + if constexpr (IsAnyOf) { honk_recursion = true; } @@ -1478,12 +1477,12 @@ int main(int argc, char* argv[]) } else if (command == "prove_keccak_ultra_honk") { std::string output_path = get_option(args, "-o", "./proofs/proof"); prove_honk(bytecode_path, witness_path, output_path); - } else if (command == "prove_keccak_ultra_honk_output_all") { + } else if (command == "prove_ultra_keccak_honk_output_all") { std::string output_path = get_option(args, "-o", "./proofs/proof"); prove_honk_output_all(bytecode_path, witness_path, output_path); } else if (command == "verify_ultra_honk") { return verify_honk(proof_path, vk_path) ? 0 : 1; - } else if (command == "verify_keccak_ultra_honk") { + } else if (command == "verify_ultra_keccak_honk") { return verify_honk(proof_path, vk_path) ? 0 : 1; } else if (command == "write_vk_ultra_honk") { std::string output_path = get_option(args, "-o", "./target/vk"); @@ -1508,6 +1507,9 @@ int main(int argc, char* argv[]) } else if (command == "vk_as_fields_mega_honk") { std::string output_path = get_option(args, "-o", vk_path + "_fields.json"); vk_as_fields_honk(vk_path, output_path); + } else if (command == "vk_as_fields_ultra_keccak_honk") { + std::string output_path = get_option(args, "-o", vk_path + "_fields.json"); + vk_as_fields_honk(vk_path, output_path); } else { std::cerr << "Unknown command: " << command << "\n"; return 1; diff --git a/barretenberg/cpp/src/barretenberg/benchmark/basics_bench/basics.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/basics_bench/basics.bench.cpp index 00da0386848..8591e02d73a 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/basics_bench/basics.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/basics_bench/basics.bench.cpp @@ -455,10 +455,10 @@ void pippenger(State& state) size_t num_cycles = 1 << static_cast(state.range(0)); Polynomial pol(num_cycles); for (size_t i = 0; i < num_cycles; i++) { - *(uint256_t*)&pol[i] = engine.get_random_uint256(); - pol[i].self_reduce_once(); - pol[i].self_reduce_once(); - pol[i].self_reduce_once(); + *(uint256_t*)&pol.at(i) = engine.get_random_uint256(); + pol.at(i).self_reduce_once(); + pol.at(i).self_reduce_once(); + pol.at(i).self_reduce_once(); } auto ck = std::make_shared>(num_cycles); diff --git a/barretenberg/cpp/src/barretenberg/benchmark/ipa_bench/ipa.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/ipa_bench/ipa.bench.cpp index e099e100826..304a0a8a1ef 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/ipa_bench/ipa.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/ipa_bench/ipa.bench.cpp @@ -35,7 +35,7 @@ void ipa_open(State& state) noexcept // Construct the polynomial Polynomial poly(n); for (size_t i = 0; i < n; ++i) { - poly[i] = Fr::random_element(&engine); + poly.at(i) = Fr::random_element(&engine); } auto x = Fr::random_element(&engine); auto eval = poly.evaluate(x); diff --git a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp index 35dce34f5fa..aad7be68295 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_bench/protogalaxy.bench.cpp @@ -4,8 +4,8 @@ #include "barretenberg/protogalaxy/protogalaxy_prover.hpp" #include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -#include "barretenberg/sumcheck/instance/instances.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" +#include "barretenberg/ultra_honk/decider_keys.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" using namespace benchmark; diff --git a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_rounds_bench/protogalaxy_rounds.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_rounds_bench/protogalaxy_rounds.bench.cpp index 650b4a8727e..da79a67adb5 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_rounds_bench/protogalaxy_rounds.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/protogalaxy_rounds_bench/protogalaxy_rounds.bench.cpp @@ -3,7 +3,7 @@ #include "barretenberg/protogalaxy/protogalaxy_prover.hpp" #include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -#include "barretenberg/sumcheck/instance/instances.hpp" +#include "barretenberg/ultra_honk/decider_keys.hpp" using namespace benchmark; diff --git a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp index 501f39a5f10..6ea39cbc4ae 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp @@ -2,8 +2,8 @@ #include "barretenberg/protogalaxy/protogalaxy_prover_internal.hpp" // just for an alias; should perhaps move to prover #include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/sumcheck/instance/instances.hpp" #include "barretenberg/translator_vm/translator_flavor.hpp" +#include "barretenberg/ultra_honk/decider_keys.hpp" #include namespace { diff --git a/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/mega_honk.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/mega_honk.bench.cpp index 57ed50a6da3..9c96968bdf4 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/mega_honk.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/mega_honk.bench.cpp @@ -26,7 +26,21 @@ static void construct_proof_megahonk_power_of_2(State& state) noexcept state, &bb::mock_circuits::generate_basic_arithmetic_circuit, log2_of_gates); } +static void get_row_power_of_2(State& state) noexcept +{ + auto log2_of_gates = static_cast(state.range(0)); + size_t gates = 1 << log2_of_gates; + MegaFlavor::ProverPolynomials polynomials{ gates }; + for (auto _ : state) { + for (size_t i = 0; i < gates; i++) { + benchmark::DoNotOptimize(polynomials.get_row(i)); + } + } +} + // Define benchmarks + +// This exists due to an issue where get_row was blowing up in time BENCHMARK_CAPTURE(construct_proof_megahonk, sha256, &stdlib::generate_sha256_test_circuit) ->Unit(kMillisecond); BENCHMARK_CAPTURE(construct_proof_megahonk, keccak, &stdlib::generate_keccak_test_circuit) @@ -40,6 +54,11 @@ BENCHMARK_CAPTURE(construct_proof_megahonk, &stdlib::generate_merkle_membership_test_circuit) ->Unit(kMillisecond); +BENCHMARK(get_row_power_of_2) + // 2**15 gates to 2**20 gates + ->DenseRange(15, 20) + ->Unit(kMillisecond); + BENCHMARK(construct_proof_megahonk_power_of_2) // 2**15 gates to 2**20 gates ->DenseRange(15, 20) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp index ec7d5dcc6b0..078e8fa98ca 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp @@ -5,7 +5,7 @@ #include "barretenberg/plonk_honk_shared/arithmetization/max_block_size_tracker.hpp" #include "barretenberg/protogalaxy/protogalaxy_prover.hpp" #include "barretenberg/protogalaxy/protogalaxy_verifier.hpp" -#include "barretenberg/sumcheck/instance/instances.hpp" +#include "barretenberg/ultra_honk/decider_keys.hpp" #include "barretenberg/ultra_honk/decider_prover.hpp" #include "barretenberg/ultra_honk/decider_verifier.hpp" #include diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp index 61f32b8d6d1..129cb4df521 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp @@ -72,4 +72,17 @@ template class OpeningClaim { bool operator==(const OpeningClaim& other) const = default; }; + +/** + * @brief An accumulator consisting of the Shplonk evaluation challenge and vectors of commitments and scalars. + * + * @details This structure is used in the `reduce_verify_batch_opening_claim` method of KZG or IPA. + * + * @tparam Curve: BN254 or Grumpkin. + */ +template struct BatchOpeningClaim { + std::vector commitments; + std::vector scalars; + typename Curve::ScalarField evaluation_point; +}; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/commit.bench.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/commit.bench.cpp index c2cd8ec68b3..33cfce2fe10 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/commit.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/commit.bench.cpp @@ -21,7 +21,7 @@ template Polynomial sparse_random_poly(const size_t size, cons for (size_t i = 0; i < num_nonzero; i++) { size_t idx = engine.get_random_uint32() % size; - polynomial[idx] = FF::random_element(); + polynomial.at(idx) = FF::random_element(); } return polynomial; @@ -55,7 +55,7 @@ template void bench_commit_sparse(::benchmark::State& state) auto polynomial = Polynomial(num_points); for (size_t i = 0; i < num_nonzero; i++) { - polynomial[i] = 1; + polynomial.at(i) = 1; } for (auto _ : state) { @@ -74,7 +74,7 @@ template void bench_commit_sparse_preprocessed(::benchmark::Sta auto polynomial = Polynomial(num_points); for (size_t i = 0; i < num_nonzero; i++) { - polynomial[i] = 1; + polynomial.at(i) = 1; } for (auto _ : state) { @@ -121,10 +121,7 @@ template void bench_commit_random(::benchmark::State& state) auto key = create_commitment_key(MAX_NUM_POINTS); const size_t num_points = 1 << state.range(0); - auto polynomial = Polynomial(num_points); - for (auto& coeff : polynomial) { - coeff = Fr::random_element(); - } + Polynomial polynomial = Polynomial::random(num_points); for (auto _ : state) { key->commit(polynomial); } @@ -137,15 +134,11 @@ template void bench_commit_random_non_power_of_2(::benchmark::S auto key = create_commitment_key(MAX_NUM_POINTS); const size_t num_points = 1 << state.range(0); - auto polynomial = Polynomial(num_points - 1); - for (auto& coeff : polynomial) { - coeff = Fr::random_element(); - } + Polynomial polynomial = Polynomial::random(num_points - 1); for (auto _ : state) { key->commit(polynomial); } } - BENCHMARK(bench_commit_zero) ->DenseRange(MIN_LOG_NUM_POINTS, MAX_LOG_NUM_POINTS) ->Unit(benchmark::kMillisecond); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp index 0759472bf83..567c32c5ba4 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp @@ -7,10 +7,12 @@ * simplify the codebase. */ +#include "barretenberg/common/debug_log.hpp" #include "barretenberg/common/op_count.hpp" #include "barretenberg/ecc/scalar_multiplication/scalar_multiplication.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/numeric/bitop/pow.hpp" +#include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/polynomial_arithmetic.hpp" #include "barretenberg/srs/factories/crs_factory.hpp" #include "barretenberg/srs/factories/file_crs_factory.hpp" @@ -79,20 +81,29 @@ template class CommitmentKey { * @param polynomial a univariate polynomial p(X) = ∑ᵢ aᵢ⋅Xⁱ * @return Commitment computed as C = [p(x)] = ∑ᵢ aᵢ⋅Gᵢ */ - Commitment commit(std::span polynomial) + Commitment commit(PolynomialSpan polynomial) { BB_OP_COUNT_TIME(); - // See constructor, we must round up the number of used srs points to a power of 2. - const size_t consumed_srs = numeric::round_up_power_2(polynomial.size()); + // We must have a power-of-2 SRS points *after* subtracting by start_index. + const size_t consumed_srs = numeric::round_up_power_2(polynomial.size()) + polynomial.start_index; + auto srs = srs::get_crs_factory()->get_prover_crs(consumed_srs); + // We only need the if (consumed_srs > srs->get_monomial_size()) { - info("Attempting to commit to a polynomial that needs ", - consumed_srs, - " points with an SRS of size ", - srs->get_monomial_size()); - ASSERT(false); + throw_or_abort(format("Attempting to commit to a polynomial that needs ", + consumed_srs, + " points with an SRS of size ", + srs->get_monomial_size())); } - return scalar_multiplication::pippenger_unsafe_optimized_for_non_dyadic_polys( - polynomial, srs->get_monomial_points(), pippenger_runtime_state); + + // Extract the precomputed point table (contains raw SRS points at even indices and the corresponding + // endomorphism point (\beta*x, -y) at odd indices). We offset by polynomial.start_index * 2 to align + // with our polynomial span. + std::span point_table = srs->get_monomial_points().subspan(polynomial.start_index * 2); + DEBUG_LOG_ALL(polynomial.span); + Commitment point = scalar_multiplication::pippenger_unsafe_optimized_for_non_dyadic_polys( + polynomial.span, point_table, pippenger_runtime_state); + DEBUG_LOG(point); + return point; }; /** @@ -105,19 +116,20 @@ template class CommitmentKey { * @param polynomial * @return Commitment */ - Commitment commit_sparse(std::span polynomial) + Commitment commit_sparse(PolynomialSpan polynomial) { BB_OP_COUNT_TIME(); - const size_t degree = polynomial.size(); - ASSERT(degree <= srs->get_monomial_size()); + const size_t poly_size = polynomial.size(); + ASSERT(polynomial.end_index() <= srs->get_monomial_size()); // Extract the precomputed point table (contains raw SRS points at even indices and the corresponding - // endomorphism point (\beta*x, -y) at odd indices). - std::span point_table = srs->get_monomial_points(); + // endomorphism point (\beta*x, -y) at odd indices). We offset by polynomial.start_index * 2 to align + // with our polynomial spann. + std::span point_table = srs->get_monomial_points().subspan(polynomial.start_index * 2); // Define structures needed to multithread the extraction of non-zero inputs - const size_t num_threads = degree >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; - const size_t block_size = degree / num_threads; + const size_t num_threads = poly_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; + const size_t block_size = poly_size / num_threads; std::vector> thread_scalars(num_threads); std::vector> thread_points(num_threads); @@ -128,7 +140,7 @@ template class CommitmentKey { for (size_t idx = start; idx < end; ++idx) { - const Fr& scalar = polynomial[idx]; + const Fr& scalar = polynomial.span[idx]; if (!scalar.is_zero()) { thread_scalars[thread_idx].emplace_back(scalar); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.test.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.test.hpp index 00d7c39343b..76956dd7ae9 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.test.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.test.hpp @@ -72,15 +72,6 @@ template class CommitmentTest : public ::testing::Test { Commitment commit(const Polynomial& polynomial) { return commitment_key->commit(polynomial); } - Polynomial random_polynomial(const size_t n) - { - Polynomial p(n); - for (size_t i = 0; i < n; ++i) { - p[i] = Fr::random_element(engine); - } - return p; - } - Fr random_element() { return Fr::random_element(engine); } OpeningPair random_eval(const Polynomial& polynomial) @@ -92,7 +83,7 @@ template class CommitmentTest : public ::testing::Test { std::pair, Polynomial> random_claim(const size_t n) { - auto polynomial = random_polynomial(n); + auto polynomial = Polynomial::random(n); auto opening_pair = random_eval(polynomial); auto commitment = commit(polynomial); auto opening_claim = OpeningClaim{ opening_pair, commitment }; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.cpp index 4422abdee0d..679857e1d66 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.cpp @@ -150,7 +150,7 @@ GeminiProverOutput GeminiProver_::compute_fold_polynomial_evaluati Polynomial& batched_G = gemini_polynomials[1]; // G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X) // Compute univariate opening queries rₗ = r^{2ˡ} for l = 0, 1, ..., m-1 - std::vector r_squares = gemini::squares_of_r(r_challenge, num_variables); + std::vector r_squares = gemini::powers_of_evaluation_challenge(r_challenge, num_variables); // Compute G/r Fr r_inv = r_challenge.invert(); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index 23142078def..bc3034bc753 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -88,7 +88,7 @@ template inline std::vector powers_of_rho(const Fr rho, const siz * @param num_squares The number of foldings * @return std::vector */ -template inline std::vector squares_of_r(const Fr r, const size_t num_squares) +template inline std::vector powers_of_evaluation_challenge(const Fr r, const size_t num_squares) { std::vector squares = { r }; squares.reserve(num_squares); @@ -132,7 +132,7 @@ template class GeminiVerifier_ { * (Cⱼ, Aⱼ(-r^{2ʲ}), -r^{2}), j = [1, ..., m-1] */ static std::vector> reduce_verification(std::span mle_opening_point, /* u */ - const Fr batched_evaluation, /* all */ + Fr& batched_evaluation, /* all */ GroupElement& batched_f, /* unshifted */ GroupElement& batched_g, /* to-be-shifted */ auto& transcript) @@ -140,28 +140,17 @@ template class GeminiVerifier_ { const size_t num_variables = mle_opening_point.size(); // Get polynomials Fold_i, i = 1,...,m-1 from transcript - std::vector commitments; - commitments.reserve(num_variables - 1); - for (size_t i = 0; i < num_variables - 1; ++i) { - auto commitment = - transcript->template receive_from_prover("Gemini:FOLD_" + std::to_string(i + 1)); - commitments.emplace_back(commitment); - } + const std::vector commitments = get_gemini_commitments(num_variables, transcript); // compute vector of powers of random evaluation point r const Fr r = transcript->template get_challenge("Gemini:r"); - std::vector r_squares = gemini::squares_of_r(r, num_variables); + const std::vector r_squares = gemini::powers_of_evaluation_challenge(r, num_variables); // Get evaluations a_i, i = 0,...,m-1 from transcript - std::vector evaluations; - evaluations.reserve(num_variables); - for (size_t i = 0; i < num_variables; ++i) { - auto eval = transcript->template receive_from_prover("Gemini:a_" + std::to_string(i)); - evaluations.emplace_back(eval); - } - + const std::vector evaluations = get_gemini_evaluations(num_variables, transcript); // Compute evaluation A₀(r) - auto a_0_pos = compute_eval_pos(batched_evaluation, mle_opening_point, r_squares, evaluations); + auto a_0_pos = + compute_gemini_batched_univariate_evaluation(batched_evaluation, mle_opening_point, r_squares, evaluations); // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] + r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] // C₀_r_pos = ∑ⱼ ρʲ⋅[fⱼ] - r⁻¹⋅∑ⱼ ρᵏ⁺ʲ [gⱼ] @@ -183,42 +172,75 @@ template class GeminiVerifier_ { return fold_polynomial_opening_claims; } - private: + static std::vector get_gemini_commitments(const size_t log_circuit_size, auto& transcript) + { + std::vector gemini_commitments; + gemini_commitments.reserve(log_circuit_size - 1); + for (size_t i = 0; i < log_circuit_size - 1; ++i) { + const Commitment commitment = + transcript->template receive_from_prover("Gemini:FOLD_" + std::to_string(i + 1)); + gemini_commitments.emplace_back(commitment); + } + return gemini_commitments; + } + static std::vector get_gemini_evaluations(const size_t log_circuit_size, auto& transcript) + { + std::vector gemini_evaluations; + gemini_evaluations.reserve(log_circuit_size); + for (size_t i = 0; i < log_circuit_size; ++i) { + const Fr evaluation = transcript->template receive_from_prover("Gemini:a_" + std::to_string(i)); + gemini_evaluations.emplace_back(evaluation); + } + return gemini_evaluations; + } + /** * @brief Compute the expected evaluation of the univariate commitment to the batched polynomial. * - * @param batched_mle_eval The evaluation of the folded polynomials - * @param mle_vars MLE opening point u - * @param r_squares squares of r, r², ..., r^{2ᵐ⁻¹} - * @param fold_polynomial_evals series of Aᵢ₋₁(−r^{2ⁱ⁻¹}) - * @return evaluation A₀(r) + * Compute the evaluation \f$ A_0(r) = \sum \rho^i \cdot f_i + \frac{1}{r} \cdot \sum \rho^{i+k} g_i \f$, where \f$ + * k \f$ is the number of "unshifted" commitments. + * + * @details Initialize \f$ A_{d}(r) \f$ with the batched evaluation \f$ \sum \rho^i f_i(\vec{u}) + \sum \rho^{i+k} + * g_i(\vec{u}) \f$. The folding property ensures that + * \f{align}{ + * A_\ell\left(r^{2^\ell}\right) = (1 - u_{\ell-1}) \cdot \frac{A_{\ell-1}\left(r^{2^{\ell-1}}\right) + + * A_{\ell-1}\left(-r^{2^{\ell-1}}\right)}{2} + * + u_{\ell-1} \cdot \frac{A_{\ell-1}\left(r^{2^{\ell-1}}\right) - + * A_{\ell-1}\left(-r^{2^{\ell-1}}\right)}{2r^{2^{\ell-1}}} + * \f} + * Therefore, the verifier can recover \f$ A_0(r) \f$ by solving several linear equations. + * + * @param batched_mle_eval The evaluation of the batched polynomial at \f$ (u_0, \ldots, u_{d-1})\f$. + * @param evaluation_point Evaluation point \f$ (u_0, \ldots, u_{d-1}) \f$. + * @param challenge_powers Powers of \f$ r \f$, \f$ r^2 \), ..., \( r^{2^{m-1}} \f$. + * @param fold_polynomial_evals Evaluations \f$ A_{i-1}(-r^{2^{i-1}}) \f$. + * @return Evaluation \f$ A_0(r) \f$. */ - static Fr compute_eval_pos(const Fr batched_mle_eval, - std::span mle_vars, - std::span r_squares, - std::span fold_polynomial_evals) + static Fr compute_gemini_batched_univariate_evaluation(Fr& batched_eval_accumulator, + std::span evaluation_point, + std::span challenge_powers, + std::span fold_polynomial_evals) { - const size_t num_variables = mle_vars.size(); + const size_t num_variables = evaluation_point.size(); const auto& evals = fold_polynomial_evals; - // Initialize eval_pos with batched MLE eval v = ∑ⱼ ρʲ vⱼ + ∑ⱼ ρᵏ⁺ʲ v↺ⱼ - Fr eval_pos = batched_mle_eval; + // Solve the sequence of linear equations for (size_t l = num_variables; l != 0; --l) { - const Fr r = r_squares[l - 1]; // = rₗ₋₁ = r^{2ˡ⁻¹} - const Fr eval_neg = evals[l - 1]; // = Aₗ₋₁(−r^{2ˡ⁻¹}) - const Fr u = mle_vars[l - 1]; // = uₗ₋₁ - - // The folding property ensures that - // Aₗ₋₁(r^{2ˡ⁻¹}) + Aₗ₋₁(−r^{2ˡ⁻¹}) Aₗ₋₁(r^{2ˡ⁻¹}) - Aₗ₋₁(−r^{2ˡ⁻¹}) - // Aₗ(r^{2ˡ}) = (1-uₗ₋₁) ----------------------------- + uₗ₋₁ ----------------------------- - // 2 2r^{2ˡ⁻¹} - // We solve the above equation in Aₗ₋₁(r^{2ˡ⁻¹}), using the previously computed Aₗ(r^{2ˡ}) in eval_pos - // and using Aₗ₋₁(−r^{2ˡ⁻¹}) sent by the prover in the proof. - eval_pos = ((r * eval_pos * 2) - eval_neg * (r * (Fr(1) - u) - u)) / (r * (Fr(1) - u) + u); + // Get r²⁽ˡ⁻¹⁾ + const Fr& challenge_power = challenge_powers[l - 1]; + // Get A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾) + const Fr& eval_neg = evals[l - 1]; + // Get uₗ₋₁ + const Fr& u = evaluation_point[l - 1]; + // Compute the numerator + batched_eval_accumulator = + ((challenge_power * batched_eval_accumulator * 2) - eval_neg * (challenge_power * (Fr(1) - u) - u)); + // Divide by the denominator + batched_eval_accumulator *= (challenge_power * (Fr(1) - u) + u).invert(); } - return eval_pos; // return A₀(r) + return batched_eval_accumulator; } /** diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp index 7e378bba250..1da66356c64 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.test.cpp @@ -14,14 +14,13 @@ template class GeminiTest : public CommitmentTest { using GeminiVerifier = GeminiVerifier_; using Fr = typename Curve::ScalarField; using GroupElement = typename Curve::Element; - using Polynomial = typename bb::Polynomial; public: void execute_gemini_and_verify_claims(size_t log_n, std::vector multilinear_evaluation_point, std::vector multilinear_evaluations, - std::vector> multilinear_polynomials, - std::vector> multilinear_polynomials_to_be_shifted, + std::vector> multilinear_polynomials, + std::vector> multilinear_polynomials_to_be_shifted, std::vector multilinear_commitments, std::vector multilinear_commitments_to_be_shifted) { @@ -37,8 +36,8 @@ template class GeminiTest : public CommitmentTest { batched_evaluation += multilinear_evaluations[i] * rhos[i]; } - Polynomial batched_unshifted(1 << log_n); - Polynomial batched_to_be_shifted(1 << log_n); + Polynomial batched_unshifted(1 << log_n); + Polynomial batched_to_be_shifted = Polynomial::shiftable(1 << log_n); GroupElement batched_commitment_unshifted = GroupElement::zero(); GroupElement batched_commitment_to_be_shifted = GroupElement::zero(); const size_t num_unshifted = multilinear_polynomials.size(); @@ -113,14 +112,14 @@ TYPED_TEST(GeminiTest, Single) const size_t log_n = 4; auto u = this->random_evaluation_point(log_n); - auto poly = this->random_polynomial(n); + auto poly = Polynomial::random(n); auto commitment = this->commit(poly); auto eval = poly.evaluate_mle(u); // Collect multilinear polynomials evaluations, and commitments for input to prover/verifier std::vector multilinear_evaluations = { eval }; - std::vector> multilinear_polynomials = { poly }; - std::vector> multilinear_polynomials_to_be_shifted = {}; + std::vector> multilinear_polynomials = { poly.share() }; + std::vector> multilinear_polynomials_to_be_shifted = {}; std::vector multilinear_commitments = { commitment }; std::vector multilinear_commitments_to_be_shifted = {}; @@ -144,16 +143,15 @@ TYPED_TEST(GeminiTest, SingleShift) auto u = this->random_evaluation_point(log_n); // shiftable polynomial must have 0 as last coefficient - auto poly = this->random_polynomial(n); - poly[0] = Fr::zero(); + auto poly = Polynomial::random(n, /*shiftable*/ 1); auto commitment = this->commit(poly); auto eval_shift = poly.evaluate_mle(u, true); // Collect multilinear polynomials evaluations, and commitments for input to prover/verifier std::vector multilinear_evaluations = { eval_shift }; - std::vector> multilinear_polynomials = {}; - std::vector> multilinear_polynomials_to_be_shifted = { poly }; + std::vector> multilinear_polynomials = {}; + std::vector> multilinear_polynomials_to_be_shifted = { poly.share() }; std::vector multilinear_commitments = {}; std::vector multilinear_commitments_to_be_shifted = { commitment }; @@ -176,8 +174,8 @@ TYPED_TEST(GeminiTest, Double) auto u = this->random_evaluation_point(log_n); - auto poly1 = this->random_polynomial(n); - auto poly2 = this->random_polynomial(n); + auto poly1 = Polynomial::random(n); + auto poly2 = Polynomial::random(n); auto commitment1 = this->commit(poly1); auto commitment2 = this->commit(poly2); @@ -187,8 +185,8 @@ TYPED_TEST(GeminiTest, Double) // Collect multilinear polynomials evaluations, and commitments for input to prover/verifier std::vector multilinear_evaluations = { eval1, eval2 }; - std::vector> multilinear_polynomials = { poly1, poly2 }; - std::vector> multilinear_polynomials_to_be_shifted = {}; + std::vector> multilinear_polynomials = { poly1.share(), poly2.share() }; + std::vector> multilinear_polynomials_to_be_shifted = {}; std::vector multilinear_commitments = { commitment1, commitment2 }; std::vector multilinear_commitments_to_be_shifted = {}; @@ -211,9 +209,8 @@ TYPED_TEST(GeminiTest, DoubleWithShift) auto u = this->random_evaluation_point(log_n); - auto poly1 = this->random_polynomial(n); - auto poly2 = this->random_polynomial(n); - poly2[0] = Fr::zero(); // necessary for polynomial to be 'shiftable' + auto poly1 = Polynomial::random(n); + auto poly2 = Polynomial::random(n, 1); // make 'shiftable' auto commitment1 = this->commit(poly1); auto commitment2 = this->commit(poly2); @@ -224,8 +221,8 @@ TYPED_TEST(GeminiTest, DoubleWithShift) // Collect multilinear polynomials evaluations, and commitments for input to prover/verifier std::vector multilinear_evaluations = { eval1, eval2, eval2_shift }; - std::vector> multilinear_polynomials = { poly1, poly2 }; - std::vector> multilinear_polynomials_to_be_shifted = { poly2 }; + std::vector> multilinear_polynomials = { poly1.share(), poly2.share() }; + std::vector> multilinear_polynomials_to_be_shifted = { poly2.share() }; std::vector multilinear_commitments = { commitment1, commitment2 }; std::vector multilinear_commitments_to_be_shifted = { commitment2 }; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp index 45b1bf209ab..129e5265480 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp @@ -1,5 +1,6 @@ #pragma once #include "barretenberg/commitment_schemes/claim.hpp" +#include "barretenberg/commitment_schemes/utils/batch_mul_native.hpp" #include "barretenberg/commitment_schemes/verification_key.hpp" #include "barretenberg/common/assert.hpp" #include "barretenberg/common/container.hpp" @@ -162,7 +163,8 @@ template class IPA { // Step 4. // Set initial vector a to the polynomial monomial coefficients and load vector G - auto a_vec = polynomial; + // Ensure the polynomial copy is fully-formed + auto a_vec = polynomial.full(); std::span srs_elements = ck->srs->get_monomial_points(); std::vector G_vec_local(poly_length); @@ -217,16 +219,16 @@ template class IPA { }, thread_heuristics::FF_ADDITION_COST * 2 + thread_heuristics::FF_MULTIPLICATION_COST * 2); // Sum inner product contributions computed in parallel and unpack the std::pair auto [inner_prod_L, inner_prod_R] = sum_pairs(inner_prods); - // Step 6.a (using letters, because doxygen automaticall converts the sublist counters to letters :( ) + // Step 6.a (using letters, because doxygen automatically converts the sublist counters to letters :( ) // L_i = < a_vec_lo, G_vec_hi > + inner_prod_L * aux_generator L_i = bb::scalar_multiplication::pippenger_without_endomorphism_basis_points( - {&a_vec[0], /*size*/ round_size}, {&G_vec_local[round_size], /*size*/ round_size}, ck->pippenger_runtime_state); + {&a_vec.at(0), /*size*/ round_size}, {&G_vec_local[round_size], /*size*/ round_size}, ck->pippenger_runtime_state); L_i += aux_generator * inner_prod_L; // Step 6.b // R_i = < a_vec_hi, G_vec_lo > + inner_prod_R * aux_generator R_i = bb::scalar_multiplication::pippenger_without_endomorphism_basis_points( - {&a_vec[round_size], /*size*/ round_size}, {&G_vec_local[0], /*size*/ round_size}, ck->pippenger_runtime_state); + {&a_vec.at(round_size), /*size*/ round_size}, {&G_vec_local[0], /*size*/ round_size}, ck->pippenger_runtime_state); R_i += aux_generator * inner_prod_R; // Step 6.c @@ -262,7 +264,7 @@ template class IPA { parallel_for_heuristic( round_size, [&](size_t j) { - a_vec[j] += round_challenge * a_vec[round_size + j]; + a_vec.at(j) += round_challenge * a_vec[round_size + j]; b_vec[j] += round_challenge_inv * b_vec[round_size + j]; }, thread_heuristics::FF_ADDITION_COST * 2 + thread_heuristics::FF_MULTIPLICATION_COST * 2); } @@ -579,6 +581,49 @@ template class IPA { { return reduce_verify_internal(vk, opening_claim, transcript); } + /** + * @brief A method that produces an IPA opening claim from Shplemini accumulator containing vectors of commitments + * and scalars and a Shplonk evaluation challenge. + * + * @details Compute the commitment \f$ C \f$ that will be used to prove that Shplonk batching is performed correctly + * and check the evaluation claims of the batched univariate polynomials. The check is done by verifying that the + * polynomial corresponding to \f$ C \f$ evaluates to \f$ 0 \f$ at the Shplonk challenge point \f$ z \f$. + * + */ + static OpeningClaim reduce_batch_opening_claim( + const BatchOpeningClaim& batch_opening_claim) + { + using Utils = CommitmentSchemesUtils; + // Extract batch_mul arguments from the accumulator + const auto& commitments = batch_opening_claim.commitments; + const auto& scalars = batch_opening_claim.scalars; + const Fr& shplonk_eval_challenge = batch_opening_claim.evaluation_point; + // Compute \f$ C = \sum \text{commitments}_i \cdot \text{scalars}_i \f$ + GroupElement shplonk_output_commitment; + if constexpr (Curve::is_stdlib_type) { + shplonk_output_commitment = + GroupElement::batch_mul(commitments, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); + } else { + shplonk_output_commitment = Utils::batch_mul_native(commitments, scalars); + } + // Output an opening claim to be verified by the IPA opening protocol + return { { shplonk_eval_challenge, Fr(0) }, shplonk_output_commitment }; + } + /** + * @brief Verify the IPA opening claim obtained from a Shplemini accumulator + * + * @param batch_opening_claim + * @param vk + * @param transcript + * @return VerifierAccumulator + */ + static VerifierAccumulator reduce_verify_batch_opening_claim(const BatchOpeningClaim& batch_opening_claim, + const std::shared_ptr& vk, + auto& transcript) + { + const auto opening_claim = reduce_batch_opening_claim(batch_opening_claim); + return reduce_verify_internal(vk, opening_claim, transcript); + } }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index e03803a0132..97f2b87b297 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -1,5 +1,6 @@ #include "../gemini/gemini.hpp" +#include "../shplonk/shplemini_verifier.hpp" #include "../shplonk/shplonk.hpp" #include "./mock_transcript.hpp" #include "barretenberg/commitment_schemes/commitment_key.test.hpp" @@ -22,6 +23,7 @@ class IPATest : public CommitmentTest { using CK = CommitmentKey; using VK = VerifierCommitmentKey; using Polynomial = bb::Polynomial; + using Commitment = typename Curve::AffineElement; }; } // namespace @@ -33,9 +35,9 @@ TEST_F(IPATest, CommitOnManyZeroCoeffPolyWorks) constexpr size_t n = 4; Polynomial p(n); for (size_t i = 0; i < n - 1; i++) { - p[i] = Fr::zero(); + p.at(i) = Fr::zero(); } - p[3] = Fr::one(); + p.at(3) = Fr::one(); GroupElement commitment = this->commit(p); auto srs_elements = this->ck()->srs->get_monomial_points(); GroupElement expected = srs_elements[0] * p[0]; @@ -82,7 +84,7 @@ TEST_F(IPATest, OpenAtZero) using IPA = IPA; // generate a random polynomial, degree needs to be a power of two size_t n = 128; - auto poly = this->random_polynomial(n); + auto poly = Polynomial::random(n); Fr x = Fr::zero(); auto eval = poly.evaluate(x); auto commitment = this->commit(poly); @@ -108,7 +110,7 @@ TEST_F(IPATest, ChallengesAreZero) using IPA = IPA; // generate a random polynomial, degree needs to be a power of two size_t n = 128; - auto poly = this->random_polynomial(n); + auto poly = Polynomial::random(n); auto [x, eval] = this->random_eval(poly); auto commitment = this->commit(poly); const OpeningPair opening_pair = { x, eval }; @@ -156,8 +158,8 @@ TEST_F(IPATest, AIsZeroAfterOneRound) size_t n = 4; auto poly = Polynomial(n); for (size_t i = 0; i < n / 2; i++) { - poly[i] = Fr::random_element(); - poly[i + (n / 2)] = poly[i]; + poly.at(i) = Fr::random_element(); + poly.at(i + (n / 2)) = poly[i]; } auto [x, eval] = this->random_eval(poly); auto commitment = this->commit(poly); @@ -194,7 +196,7 @@ TEST_F(IPATest, AIsZeroAfterOneRound) TEST_F(IPATest, Commit) { constexpr size_t n = 128; - auto poly = this->random_polynomial(n); + auto poly = Polynomial::random(n); GroupElement commitment = this->commit(poly); auto srs_elements = this->ck()->srs->get_monomial_points(); GroupElement expected = srs_elements[0] * poly[0]; @@ -212,7 +214,7 @@ TEST_F(IPATest, Open) using IPA = IPA; // generate a random polynomial, degree needs to be a power of two size_t n = 128; - auto poly = this->random_polynomial(n); + auto poly = Polynomial::random(n); auto [x, eval] = this->random_eval(poly); auto commitment = this->commit(poly); const OpeningPair opening_pair = { x, eval }; @@ -246,10 +248,9 @@ TEST_F(IPATest, GeminiShplonkIPAWithShift) // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random // point. - const auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' - auto poly1 = this->random_polynomial(n); - auto poly2 = this->random_polynomial(n); - poly2[0] = Fr::zero(); // this property is required of polynomials whose shift is used + auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' + auto poly1 = Polynomial::random(n); + auto poly2 = Polynomial::random(n, /*shiftable*/ 1); GroupElement commitment1 = this->commit(poly1); GroupElement commitment2 = this->commit(poly2); @@ -268,7 +269,7 @@ TEST_F(IPATest, GeminiShplonkIPAWithShift) } Polynomial batched_unshifted(n); - Polynomial batched_to_be_shifted(n); + Polynomial batched_to_be_shifted = Polynomial::shiftable(n); batched_unshifted.add_scaled(poly1, rhos[0]); batched_unshifted.add_scaled(poly2, rhos[1]); batched_to_be_shifted.add_scaled(poly2, rhos[2]); @@ -321,3 +322,85 @@ TEST_F(IPATest, GeminiShplonkIPAWithShift) EXPECT_EQ(result, true); } +TEST_F(IPATest, ShpleminiIPAWithShift) +{ + using IPA = IPA; + using ShplonkProver = ShplonkProver_; + using ShpleminiVerifier = ShpleminiVerifier_; + using GeminiProver = GeminiProver_; + + const size_t n = 8; + const size_t log_n = 3; + + // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random + // point. + auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' + auto poly1 = Polynomial::random(n); + auto poly2 = Polynomial::random(n, /*shiftable*/ 1); + Commitment commitment1 = this->commit(poly1); + Commitment commitment2 = this->commit(poly2); + std::vector unshifted_commitments = { commitment1, commitment2 }; + std::vector shifted_commitments = { commitment2 }; + auto eval1 = poly1.evaluate_mle(mle_opening_point); + auto eval2 = poly2.evaluate_mle(mle_opening_point); + auto eval2_shift = poly2.evaluate_mle(mle_opening_point, true); + + std::vector multilinear_evaluations = { eval1, eval2, eval2_shift }; + + auto prover_transcript = NativeTranscript::prover_init_empty(); + Fr rho = prover_transcript->template get_challenge("rho"); + std::vector rhos = gemini::powers_of_rho(rho, multilinear_evaluations.size()); + + Fr batched_evaluation = Fr::zero(); + for (size_t i = 0; i < rhos.size(); ++i) { + batched_evaluation += multilinear_evaluations[i] * rhos[i]; + } + + Polynomial batched_unshifted(n); + Polynomial batched_to_be_shifted = Polynomial::shiftable(n); + batched_unshifted.add_scaled(poly1, rhos[0]); + batched_unshifted.add_scaled(poly2, rhos[1]); + batched_to_be_shifted.add_scaled(poly2, rhos[2]); + + auto gemini_polynomials = GeminiProver::compute_gemini_polynomials( + mle_opening_point, std::move(batched_unshifted), std::move(batched_to_be_shifted)); + + for (size_t l = 0; l < log_n - 1; ++l) { + std::string label = "FOLD_" + std::to_string(l + 1); + auto commitment = this->ck()->commit(gemini_polynomials[l + 2]); + prover_transcript->send_to_verifier(label, commitment); + } + + const Fr r_challenge = prover_transcript->template get_challenge("Gemini:r"); + + const auto [gemini_opening_pairs, gemini_witnesses] = GeminiProver::compute_fold_polynomial_evaluations( + mle_opening_point, std::move(gemini_polynomials), r_challenge); + + std::vector> opening_claims; + + for (size_t l = 0; l < log_n; ++l) { + std::string label = "Gemini:a_" + std::to_string(l); + const auto& evaluation = gemini_opening_pairs[l + 1].evaluation; + prover_transcript->send_to_verifier(label, evaluation); + opening_claims.emplace_back(gemini_witnesses[l], gemini_opening_pairs[l]); + } + opening_claims.emplace_back(gemini_witnesses[log_n], gemini_opening_pairs[log_n]); + + const auto opening_claim = ShplonkProver::prove(this->ck(), opening_claims, prover_transcript); + IPA::compute_opening_proof(this->ck(), opening_claim, prover_transcript); + + auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + + const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(log_n, + RefVector(unshifted_commitments), + RefVector(shifted_commitments), + RefVector(multilinear_evaluations), + mle_opening_point, + this->vk()->get_g1_identity(), + verifier_transcript); + + auto result = IPA::reduce_verify_batch_opening_claim(batch_opening_claim, this->vk(), verifier_transcript); + // auto result = IPA::reduce_verify(this->vk(), shplonk_verifier_claim, verifier_transcript); + + EXPECT_EQ(result, true); +} diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp index 0a1a873412c..0fab4113fab 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp @@ -2,6 +2,7 @@ #include "../claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/commitment_schemes/utils/batch_mul_native.hpp" #include "barretenberg/commitment_schemes/verification_key.hpp" #include "barretenberg/transcript/transcript.hpp" @@ -36,7 +37,7 @@ template class KZG { { Polynomial quotient = opening_claim.polynomial; OpeningPair pair = opening_claim.opening_pair; - quotient[0] -= pair.evaluation; + quotient.at(0) = quotient[0] - pair.evaluation; // Computes the coefficients for the quotient polynomial q(X) = (p(X) - v) / (X - r) through an FFT quotient.factor_roots(pair.challenge); auto quotient_commitment = ck->commit(quotient); @@ -54,7 +55,7 @@ template class KZG { * @param claim OpeningClaim ({r, v}, C) * @return {P₀, P₁} where * - P₀ = C − v⋅[1]₁ + r⋅[W(x)]₁ - * - P₁ = [W(x)]₁ + * - P₁ = - [W(x)]₁ */ template static VerifierAccumulator reduce_verify(const OpeningClaim& claim, @@ -85,5 +86,50 @@ template class KZG { auto P_1 = -quotient_commitment; return { P_0, P_1 }; }; + + /** + * @brief Computes the input points for the pairing check needed to verify a KZG opening claim obtained from a + * Shplemini accumulator. + * + * @details This function is used in a recursive setting where we want to "aggregate" proofs. In the Shplemini case, + * the commitment \f$ C \f$ is encoded into the vectors `commitments` and `scalars` contained in the + * `batch_opening_claim`. More explicitly, \f$ C = \sum \text{commitments}_i \cdot \text{scalars}_i \f$. To avoid + * performing an extra `batch_mul`, we simply add the commitment \f$ [W]_1 \f$ to the vector of commitments and + * the Shplonk evaluation challenge to the vector of scalars and perform a single batch_mul that computes \f$C + + * W\cdot z \f$. + * + * @param batch_opening_claim \f$(\text{commitments}, \text{scalars}, \text{shplonk_evaluation_challenge})\f$ + * A struct containing the commitments, scalars, and the Shplonk evaluation challenge. + * @return \f$ \{P_0, P_1\}\f$ where: + * - \f$ P_0 = C + [W(x)]_1 \cdot z \f$ + * - \f$ P_1 = - [W(x)]_1 \f$ + */ + template + static VerifierAccumulator reduce_verify_batch_opening_claim(BatchOpeningClaim batch_opening_claim, + const std::shared_ptr& transcript) + { + using Utils = CommitmentSchemesUtils; + auto quotient_commitment = transcript->template receive_from_prover("KZG:W"); + + // The pairing check can be expressed as + // e(C + [W]₁ ⋅ z, [1]₂) * e(−[W]₁, [X]₂) = 1, where C = ∑ commitmentsᵢ ⋅ scalarsᵢ. + GroupElement P_0; + // Place the commitment to W to 'commitments' + batch_opening_claim.commitments.emplace_back(quotient_commitment); + // Update the scalars by adding the Shplonk evaluation challenge z + batch_opening_claim.scalars.emplace_back(batch_opening_claim.evaluation_point); + // Compute C + [W]₁ ⋅ z + if constexpr (Curve::is_stdlib_type) { + P_0 = GroupElement::batch_mul(batch_opening_claim.commitments, + batch_opening_claim.scalars, + /*max_num_bits=*/0, + /*with_edgecases=*/true); + } else { + P_0 = Utils::batch_mul_native(batch_opening_claim.commitments, batch_opening_claim.scalars); + } + auto P_1 = -quotient_commitment; + + return { P_0, P_1 }; + } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index 19ead96b61f..65422a1777b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -1,6 +1,7 @@ #include "kzg.hpp" #include "../gemini/gemini.hpp" +#include "../shplonk/shplemini_verifier.hpp" #include "../shplonk/shplonk.hpp" #include "../commitment_key.test.hpp" @@ -30,7 +31,7 @@ TYPED_TEST(KZGTest, single) using KZG = KZG; using Fr = typename TypeParam::ScalarField; - auto witness = this->random_polynomial(n); + auto witness = Polynomial::random(n); g1::element commitment = this->commit(witness); auto challenge = Fr::random_element(); @@ -72,10 +73,9 @@ TYPED_TEST(KZGTest, GeminiShplonkKzgWithShift) // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random // point. - const auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' - auto poly1 = this->random_polynomial(n); - auto poly2 = this->random_polynomial(n); - poly2[0] = Fr::zero(); // this property is required of polynomials whose shift is used + auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' + auto poly1 = Polynomial::random(n); + auto poly2 = Polynomial::random(n, 1); // make 'shiftable' GroupElement commitment1 = this->commit(poly1); GroupElement commitment2 = this->commit(poly2); @@ -97,7 +97,7 @@ TYPED_TEST(KZGTest, GeminiShplonkKzgWithShift) // Compute batched polynomials Polynomial batched_unshifted(n); - Polynomial batched_to_be_shifted(n); + Polynomial batched_to_be_shifted = Polynomial::shiftable(n); batched_unshifted.add_scaled(poly1, rhos[0]); batched_unshifted.add_scaled(poly2, rhos[1]); batched_to_be_shifted.add_scaled(poly2, rhos[2]); @@ -172,4 +172,114 @@ TYPED_TEST(KZGTest, GeminiShplonkKzgWithShift) EXPECT_EQ(this->vk()->pairing_check(pairing_points[0], pairing_points[1]), true); } +TYPED_TEST(KZGTest, ShpleminiKzgWithShift) +{ + using ShplonkProver = ShplonkProver_; + using GeminiProver = GeminiProver_; + using ShpleminiVerifier = ShpleminiVerifier_; + using KZG = KZG; + using Fr = typename TypeParam::ScalarField; + using GroupElement = typename TypeParam::Element; + using Commitment = typename TypeParam::AffineElement; + using Polynomial = typename bb::Polynomial; + + const size_t n = 16; + const size_t log_n = 4; + auto prover_transcript = NativeTranscript::prover_init_empty(); + // Get batching challenge + Fr rho = prover_transcript->template get_challenge("rho"); + // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random + // point. + auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' + auto poly1 = Polynomial::random(n); + auto poly2 = Polynomial::random(n, /*shiftable*/ 1); + + Commitment commitment1 = this->commit(poly1); + Commitment commitment2 = this->commit(poly2); + std::vector unshifted_commitments = { commitment1, commitment2 }; + std::vector shifted_commitments = { commitment2 }; + auto eval1 = poly1.evaluate_mle(mle_opening_point); + auto eval2 = poly2.evaluate_mle(mle_opening_point); + auto eval2_shift = poly2.evaluate_mle(mle_opening_point, true); + + // Collect multilinear evaluations for input to prover + std::vector multilinear_evaluations = { eval1, eval2, eval2_shift }; + + std::vector rhos = gemini::powers_of_rho(rho, multilinear_evaluations.size()); + + // Compute batched multivariate evaluation + Fr batched_evaluation = Fr::zero(); + for (size_t i = 0; i < rhos.size(); ++i) { + batched_evaluation += multilinear_evaluations[i] * rhos[i]; + } + + // Compute batched polynomials + Polynomial batched_unshifted(n); + Polynomial batched_to_be_shifted = Polynomial::shiftable(n); + batched_unshifted.add_scaled(poly1, rhos[0]); + batched_unshifted.add_scaled(poly2, rhos[1]); + batched_to_be_shifted.add_scaled(poly2, rhos[2]); + + // Compute batched commitments + GroupElement batched_commitment_unshifted = GroupElement::zero(); + GroupElement batched_commitment_to_be_shifted = GroupElement::zero(); + batched_commitment_unshifted = commitment1 * rhos[0] + commitment2 * rhos[1]; + batched_commitment_to_be_shifted = commitment2 * rhos[2]; + + // Run the full prover PCS protocol: + + // Compute: + // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1 + // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1 + auto gemini_polynomials = GeminiProver::compute_gemini_polynomials( + mle_opening_point, std::move(batched_unshifted), std::move(batched_to_be_shifted)); + + for (size_t l = 0; l < log_n - 1; ++l) { + std::string label = "FOLD_" + std::to_string(l + 1); + auto commitment = this->ck()->commit(gemini_polynomials[l + 2]); + prover_transcript->send_to_verifier(label, commitment); + } + + const Fr r_challenge = prover_transcript->template get_challenge("Gemini:r"); + + const auto [gemini_opening_pairs, gemini_witnesses] = GeminiProver::compute_fold_polynomial_evaluations( + mle_opening_point, std::move(gemini_polynomials), r_challenge); + + std::vector> opening_claims; + for (size_t l = 0; l < log_n; ++l) { + std::string label = "Gemini:a_" + std::to_string(l); + const auto& evaluation = gemini_opening_pairs[l + 1].evaluation; + prover_transcript->send_to_verifier(label, evaluation); + opening_claims.emplace_back(gemini_witnesses[l], gemini_opening_pairs[l]); + } + opening_claims.emplace_back(gemini_witnesses[log_n], gemini_opening_pairs[log_n]); + + // Shplonk prover output: + // - opening pair: (z_challenge, 0) + // - witness: polynomial Q - Q_z + const auto opening_claim = ShplonkProver::prove(this->ck(), opening_claims, prover_transcript); + + // KZG prover: + // - Adds commitment [W] to transcript + KZG::compute_opening_proof(this->ck(), opening_claim, prover_transcript); + + // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation) + + auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + + // Gemini verifier output: + // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 + const auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(log_n, + RefVector(unshifted_commitments), + RefVector(shifted_commitments), + RefVector(multilinear_evaluations), + mle_opening_point, + this->vk()->get_g1_identity(), + verifier_transcript); + const auto pairing_points = KZG::reduce_verify_batch_opening_claim(batch_opening_claim, verifier_transcript); + // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2) + + EXPECT_EQ(this->vk()->pairing_check(pairing_points[0], pairing_points[1]), true); +} + } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.hpp new file mode 100644 index 00000000000..53893f7b0cb --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.hpp @@ -0,0 +1,320 @@ +#pragma once +#include "barretenberg/commitment_schemes/claim.hpp" +#include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/commitment_schemes/gemini/gemini.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" +#include "barretenberg/commitment_schemes/utils/batch_mul_native.hpp" +#include "barretenberg/commitment_schemes/verification_key.hpp" +#include "barretenberg/transcript/transcript.hpp" + +namespace bb { +/** + * \brief An efficient verifier for the evaluation proofs of multilinear polynomials and their shifts. + * + * \details + * \subsection Context + * + * This Verifier combines verifiers from four protocols: + * 1. **Batch opening protocol**: Reduces various evaluation claims of multilinear polynomials and their shifts to the + * opening claim of a single batched polynomial. + * 2. **Gemini protocol**: Reduces the batched polynomial opening claim to a claim about openings of Gemini univariate + * polynomials. + * 3. **Shplonk protocol**: Reduces the opening of Gemini univariate polynomials at different points to a single opening + * of a batched univariate polynomial. Outputs \f$ \text{shplonk_opening_claim} \f$. + * 4. **KZG or IPA protocol**: Verifies the evaluation of the univariate batched by Shplonk. + * + * **Important Observation**: From step 1 to step 4, the Verifier is not required to hash any results of its group + * operations. Therefore, they could be performed at the very end, i.e. by the opening protocol of a chosen univariate + * PCS. Because of this and the shape of the pairing check in Shplonk, various batch_mul calls could be reduced to a + * single batch_mul call. This way we minimize the number of gates in the resulting recursive verifier circuits and save + * some group operations in the native setting. + * + * \remark The sequence of steps could be performed by performing batching of unshifted and shifted polynomials, feeding + * it to the existing GeminiVerifier, whose output would be passed to the ShplonkVerifier and then to the reduce_verify + * method of a chosen PCS. However, it would be less efficient than ShpleminiVerifier in terms of group and field + * operations. + * + * \subsection Implementation + * + * The method \ref compute_batch_opening_claim receives commitments to all prover polynomials, their claimed + * evaluations, the sumcheck challenge, the group element \f$ [1]_1 \f$, and a pointer to the transcript. Its logic + * could be divided into several steps: + * + * 1. Receive most of the challenges and prover data. + * 2. Run the \ref batch_multivariate_opening_claims method corresponding to step 1 above. + * 3. Corresponding to step 2 above: + * - Run the \ref batch_gemini_claims_received_from_prover method. + * - Compute the evaluation of the Gemini batched univariate. + * 4. Output a \ref bb::BatchOpeningClaim "batch opening claim", which is a atriple \f$ (\text{commitments}, + * \text{scalars}, \text{shplonk_evaluation_point}) \f$ that satisfies the following: \f[ \text{batch_mul} + * (\text{commitments},\ \text{scalars}) = \text{shplonk_opening_claim}.\text{point} \f] and the sizes of 'commitments' + * and 'scalars' are equal to: \f[ + * \#\text{claimed_evaluations} + \text{log_circuit_size} + 2 + * \f] + * + * The output triple is either fed to the corresponding \ref bb::KZG< Curve_ >::reduce_verify_batch_opening_claim + * "KZG method" or \ref bb::IPA< Curve_ >::reduce_verify_batch_opening_claim "IPA method". In the case of KZG, we reduce + * \f$ 6 \f$ batch_mul calls needed for the verification of the multivariate evaluation claims to the single batch_mul + * described above. In the case of IPA, the total number of batch_mul calls needed to verify the multivariate evaluation + * claims is reduced by \f$ 5 \f$. + * + * TODO (https://github.com/AztecProtocol/barretenberg/issues/1084) Reduce the size of batch_mul further by eliminating + * shifted commitments. + */ + +template class ShpleminiVerifier_ { + using Fr = typename Curve::ScalarField; + using GroupElement = typename Curve::Element; + using Commitment = typename Curve::AffineElement; + using VK = VerifierCommitmentKey; + using ShplonkVerifier = ShplonkVerifier_; + using GeminiVerifier = GeminiVerifier_; + + public: + template + static BatchOpeningClaim compute_batch_opening_claim(const Fr log_N, + RefSpan unshifted_commitments, + RefSpan shifted_commitments, + RefSpan claimed_evaluations, + const std::vector& multivariate_challenge, + const Commitment& g1_identity, + std::shared_ptr& transcript) + { + // Extract log_circuit_size + size_t log_circuit_size{ 0 }; + if constexpr (Curve::is_stdlib_type) { + log_circuit_size = static_cast(log_N.get_value()); + } else { + log_circuit_size = static_cast(log_N); + } + + // Get the challenge ρ to batch commitments to multilinear polynomials and their shifts + const Fr multivariate_batching_challenge = transcript->template get_challenge("rho"); + + // Process Gemini transcript data: + // - Get Gemini commitments (com(A₁), com(A₂), … , com(Aₙ₋₁)) + const std::vector gemini_commitments = + GeminiVerifier::get_gemini_commitments(log_circuit_size, transcript); + // - Get Gemini evaluation challenge for Aᵢ, i = 0, … , d−1 + const Fr gemini_evaluation_challenge = transcript->template get_challenge("Gemini:r"); + // - Get evaluations (A₀(−r), A₁(−r²), ... , Aₙ₋₁(−r²⁽ⁿ⁻¹⁾)) + const std::vector gemini_evaluations = GeminiVerifier::get_gemini_evaluations(log_circuit_size, transcript); + // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size + const std::vector gemini_eval_challenge_powers = + gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, log_circuit_size); + + // Process Shplonk transcript data: + // - Get Shplonk batching challenge + const Fr shplonk_batching_challenge = transcript->template get_challenge("Shplonk:nu"); + // - Get the quotient commitment for the Shplonk batching of Gemini opening claims + const auto Q_commitment = transcript->template receive_from_prover("Shplonk:Q"); + + // Start populating the vector (Q, f₀, ... , fₖ₋₁, g₀, ... , gₘ₋₁, com(A₁), ... , com(Aₙ₋₁), [1]₁) + std::vector commitments{ Q_commitment }; + // Get Shplonk opening point z + const Fr shplonk_evaluation_challenge = transcript->template get_challenge("Shplonk:z"); + // Start computing the scalar to be multiplied by [1]₁ + Fr constant_term_accumulator{ 0 }; + + // Initialize the vector of scalars placing the scalar 1 correposnding to Q_commitment + std::vector scalars; + if constexpr (Curve::is_stdlib_type) { + auto builder = shplonk_batching_challenge.get_context(); + scalars.emplace_back(Fr(builder, 1)); + } else { + scalars.emplace_back(Fr(1)); + } + // Compute 1/(z − r), 1/(z + r), 1/(z + r²), … , 1/(z + r²⁽ⁿ⁻¹⁾) needed for Shplonk batching + const std::vector inverse_vanishing_evals = ShplonkVerifier::compute_inverted_gemini_denominators( + log_circuit_size + 1, shplonk_evaluation_challenge, gemini_eval_challenge_powers); + + // i-th unshifted commitment is multiplied by −ρⁱ and the unshifted_scalar ( 1/(z−r) + ν/(z+r) ) + const Fr unshifted_scalar = + inverse_vanishing_evals[0] + shplonk_batching_challenge * inverse_vanishing_evals[1]; + // i-th shifted commitment is multiplied by −ρⁱ⁺ᵏ and the shifted_scalar r⁻¹ ⋅ (1/(z−r) − ν/(z+r)) + const Fr shifted_scalar = + gemini_evaluation_challenge.invert() * + (inverse_vanishing_evals[0] - shplonk_batching_challenge * inverse_vanishing_evals[1]); + + // Place the commitments to prover polynomials in the commitments vector. Compute the evaluation of the batched + // multilinear polynomial. Populate the vector of scalars for the final batch mul + Fr batched_evaluation{ 0 }; + batch_multivariate_opening_claims(unshifted_commitments, + shifted_commitments, + claimed_evaluations, + multivariate_batching_challenge, + unshifted_scalar, + shifted_scalar, + commitments, + scalars, + batched_evaluation); + + // Place the commitments to Gemini Aᵢ to the vector of commitments, compute the contributions from + // Aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars + batch_gemini_claims_received_from_prover(log_circuit_size, + gemini_commitments, + gemini_evaluations, + inverse_vanishing_evals, + shplonk_batching_challenge, + commitments, + scalars, + constant_term_accumulator); + + // Add contributions from A₀(r) and A₀(-r) to constant_term_accumulator: + // - Compute A₀(r) + const Fr a_0_pos = GeminiVerifier_::compute_gemini_batched_univariate_evaluation( + batched_evaluation, multivariate_challenge, gemini_eval_challenge_powers, gemini_evaluations); + // - Add A₀(r)/(z−r) to the constant term accumulator + constant_term_accumulator += a_0_pos * inverse_vanishing_evals[0]; + // Add A₀(−r)/(z+r) to the constant term accumulator + constant_term_accumulator += gemini_evaluations[0] * shplonk_batching_challenge * inverse_vanishing_evals[1]; + + // Finalize the batch opening claim + commitments.emplace_back(g1_identity); + scalars.emplace_back(constant_term_accumulator); + + return { commitments, scalars, shplonk_evaluation_challenge }; + }; + /** + * @brief Populates the vectors of commitments and scalars, and computes the evaluation of the batched multilinear + * polynomial at the sumcheck challenge. + * + * @details This function iterates over all commitments and the claimed evaluations of the corresponding + * polynomials. The following notations are used: + * - \f$ \rho \f$: Batching challenge for multivariate claims. + * - \f$ z \f$: SHPLONK evaluation challenge. + * - \f$ r \f$: Gemini evaluation challenge. + * - \f$ \nu \f$: SHPLONK batching challenge. + * + * The vector of scalars is populated as follows: + * \f[ + * \left( + * - \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{i+k-1} \times \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * - \rho^{i+k} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{k+m-1} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right) + * \right) + * \f] + * + * The following vector is concatenated to the vector of commitments: + * \f[ + * f_0, \ldots, f_{m-1}, f_{\text{shift}, 0}, \ldots, f_{\text{shift}, k-1} + * \f] + * + * Simultaneously, the evaluation of the multilinear polynomial + * \f[ + * \sum \rho^i \cdot f_i + \sum \rho^{i+k} \cdot f_{\text{shift}, i} + * \f] + * at the challenge point \f$ (u_0,\ldots, u_{n-1}) \f$ is computed. + * + * This approach minimizes the number of iterations over the commitments to multilinear polynomials + * and eliminates the need to store the powers of \f$ \rho \f$. + * + * @param unshifted_commitments Commitments to unshifted polynomials. + * @param shifted_commitments Commitments to shifted polynomials. + * @param claimed_evaluations Claimed evaluations of the corresponding polynomials. + * @param multivariate_batching_challenge Random challenge used for batching of multivariate evaluation claims. + * @param unshifted_scalar Scaling factor for unshifted polynomials. + * @param shifted_scalar Scaling factor for shifted polynomials. + * @param commitments The vector of commitments to be populated. + * @param scalars The vector of scalars to be populated. + * @param batched_evaluation The evaluation of the batched multilinear polynomial. + */ + static void batch_multivariate_opening_claims(RefSpan unshifted_commitments, + RefSpan shifted_commitments, + RefSpan claimed_evaluations, + const Fr& multivariate_batching_challenge, + const Fr& unshifted_scalar, + const Fr& shifted_scalar, + std::vector& commitments, + std::vector& scalars, + Fr& batched_evaluation) + { + size_t evaluation_idx = 0; + Fr current_batching_challenge = Fr(1); + for (auto& unshifted_commitment : unshifted_commitments) { + // Move unshifted commitments to the 'commitments' vector + commitments.emplace_back(std::move(unshifted_commitment)); + // Compute −ρⁱ ⋅ (1/(z−r) + ν/(z+r)) and place into 'scalars' + scalars.emplace_back(-unshifted_scalar * current_batching_challenge); + // Accumulate the evaluation of ∑ ρⁱ ⋅ fᵢ at the sumcheck challenge + batched_evaluation += claimed_evaluations[evaluation_idx] * current_batching_challenge; + evaluation_idx += 1; + // Update the batching challenge + current_batching_challenge *= multivariate_batching_challenge; + } + for (auto& shifted_commitment : shifted_commitments) { + // Move shifted commitments to the 'commitments' vector + commitments.emplace_back(std::move(shifted_commitment)); + // Compute −ρ⁽ⁱ⁺ᵏ⁾ ⋅ r⁻¹ ⋅ (1/(z−r) − ν/(z+r)) and place into 'scalars' + scalars.emplace_back(-shifted_scalar * current_batching_challenge); + // Accumulate the evaluation of ∑ ρ⁽ⁱ⁺ᵏ⁾ ⋅ f_shift, i at the sumcheck challenge + batched_evaluation += claimed_evaluations[evaluation_idx] * current_batching_challenge; + evaluation_idx += 1; + // Update the batching challenge + current_batching_challenge *= multivariate_batching_challenge; + } + } + /** + * @brief Populates the 'commitments' and 'scalars' vectors with the commitments to Gemini fold polynomials \f$ A_i + * \f$. + * + * @details Once the commitments to Gemini "fold" polynomials \f$ A_i \f$ and their evaluations at \f$ -r^{2^i} \f$, + * where \f$ i = 1, \ldots, n-1 \f$, are received by the verifier, it performs the following operations: + * + * 1. Moves the vector + * \f[ + * \left( \text{com}(A_1), \text{com}(A_2), \ldots, \text{com}(A_{n-1}) \right) + * \f] + * to the 'commitments' vector. + * + * 2. Computes the scalars: + * \f[ + * \frac{\nu^{2}}{z + r^2}, \frac{\nu^3}{z + r^4}, \ldots, \frac{\nu^{n-1}}{z + r^{2^{n-1}}} + * \f] + * and places them into the 'scalars' vector. + * + * 3. Accumulates the summands of the constant term: + * \f[ + * \sum_{i=2}^{n-1} \frac{\nu^{i} \cdot A_i(-r^{2^i})}{z + r^{2^i}} + * \f] + * and adds them to the 'constant_term_accumulator'. + * + * @param log_circuit_size The logarithm of the circuit size, determining the depth of the Gemini protocol. + * @param gemini_commitments A vector containing the commitments to the Gemini fold polynomials \f$ A_i \f$. + * @param gemini_evaluations A vector containing the evaluations of the Gemini fold polynomials \f$ A_i \f$ at + * points \f$ -r^{2^i} \f$. + * @param inverse_vanishing_evals A vector containing the inverse evaluations of the vanishing polynomial. + * @param shplonk_batching_challenge The batching challenge \f$ \nu \f$ used in the SHPLONK protocol. + * @param commitments Output vector where the commitments to the Gemini fold polynomials will be stored. + * @param scalars Output vector where the computed scalars will be stored. + * @param constant_term_accumulator The accumulator for the summands of the constant term. + */ + static void batch_gemini_claims_received_from_prover(const size_t log_circuit_size, + const std::vector& gemini_commitments, + const std::vector& gemini_evaluations, + const std::vector& inverse_vanishing_evals, + const Fr& shplonk_batching_challenge, + std::vector& commitments, + std::vector& scalars, + Fr& constant_term_accumulator) + { + // Initialize batching challenge as ν² + Fr current_batching_challenge = shplonk_batching_challenge * shplonk_batching_challenge; + for (size_t j = 0; j < log_circuit_size - 1; ++j) { + // Compute the scaling factor (ν²⁺ⁱ) / (z + r²⁽ⁱ⁺²⁾) for i = 0, … , d-2 + Fr scaling_factor = current_batching_challenge * inverse_vanishing_evals[j + 2]; + // Place the scaling factor to the 'scalars' vector + scalars.emplace_back(-scaling_factor); + // Add Aᵢ(−r²ⁱ) for i = 1, … , n-1 to the constant term accumulator + constant_term_accumulator += scaling_factor * gemini_evaluations[j + 1]; + // Update the batching challenge + current_batching_challenge *= shplonk_batching_challenge; + // Move com(Aᵢ) to the 'commitments' vector + commitments.emplace_back(std::move(gemini_commitments[j])); + } + } +}; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.test.cpp new file mode 100644 index 00000000000..45292861fae --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini_verifier.test.cpp @@ -0,0 +1,228 @@ + +#include "shplemini_verifier.hpp" +#include "../commitment_key.test.hpp" +#include "../gemini/gemini.hpp" +#include "../kzg/kzg.hpp" +#include "../shplonk/shplonk.hpp" +#include "../utils/batch_mul_native.hpp" +#include "barretenberg/commitment_schemes/claim.hpp" +#include "barretenberg/ecc/curves/bn254/g1.hpp" + +#include +#include + +namespace bb { + +template class ShpleminiTest : public CommitmentTest { + public: + using Fr = typename Curve::ScalarField; + using Commitment = typename Curve::AffineElement; + using GroupElement = typename Curve::Element; + using Polynomial = bb::Polynomial; +}; + +using CurveTypes = ::testing::Types; + +TYPED_TEST_SUITE(ShpleminiTest, CurveTypes); + +// This test checks that batch_multivariate_opening_claims method operates correctly +TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching) +{ + using ShpleminiVerifier = ShpleminiVerifier_; + using Fr = typename TypeParam::ScalarField; + using GroupElement = typename TypeParam::Element; + using Commitment = typename TypeParam::AffineElement; + using Polynomial = typename bb::Polynomial; + using Utils = CommitmentSchemesUtils; + + const size_t n = 16; + const size_t log_n = 4; + + // Generate mock challenges + Fr rho = Fr::random_element(); + Fr gemini_eval_challenge = Fr::random_element(); + Fr shplonk_batching_challenge = Fr::random_element(); + Fr shplonk_eval_challenge = Fr::random_element(); + + // Generate multilinear polynomials and compute their commitments + auto mle_opening_point = this->random_evaluation_point(log_n); + auto poly1 = Polynomial::random(n); + auto poly2 = Polynomial::random(n, /*shiftable*/ 1); + Polynomial poly3(n); + + Commitment commitment1 = this->commit(poly1); + Commitment commitment2 = this->commit(poly2); + Commitment commitment3 = this->commit(poly3); + EXPECT_TRUE(commitment3.is_point_at_infinity()); + + std::vector unshifted_commitments = { commitment1, commitment2, commitment3 }; + std::vector shifted_commitments = { commitment2, commitment3 }; + + // Evaluate the polynomials at the multivariate challenge, poly3 is not evaluated, because it is 0. + auto eval1 = poly1.evaluate_mle(mle_opening_point); + auto eval2 = poly2.evaluate_mle(mle_opening_point); + Fr eval3{ 0 }; + Fr eval3_shift{ 0 }; + auto eval2_shift = poly2.evaluate_mle(mle_opening_point, true); + + // Collect multilinear evaluations + std::vector multilinear_evaluations = { eval1, eval2, eval3, eval2_shift, eval3_shift }; + std::vector rhos = gemini::powers_of_rho(rho, multilinear_evaluations.size()); + + // Compute batched multivariate evaluation + Fr batched_evaluation = + std::inner_product(multilinear_evaluations.begin(), multilinear_evaluations.end(), rhos.begin(), Fr::zero()); + + // Compute batched commitments manually + GroupElement batched_commitment_unshifted = commitment1 * rhos[0] + commitment2 * rhos[1] + commitment3 * rhos[2]; + GroupElement batched_commitment_to_be_shifted = commitment2 * rhos[3] + commitment3 * rhos[4]; + + // Compute expected result manually + GroupElement commitment_to_univariate = + batched_commitment_unshifted + batched_commitment_to_be_shifted * gemini_eval_challenge.invert(); + GroupElement commitment_to_univariate_neg = + batched_commitment_unshifted - batched_commitment_to_be_shifted * gemini_eval_challenge.invert(); + + GroupElement expected_result = + commitment_to_univariate * (shplonk_eval_challenge - gemini_eval_challenge).invert() + + commitment_to_univariate_neg * + (shplonk_batching_challenge * (shplonk_eval_challenge + gemini_eval_challenge).invert()); + + // Run the ShepliminiVerifier batching method + std::vector commitments; + std::vector scalars; + Fr verifier_batched_evaluation{ 0 }; + + Fr unshifted_scalar = (shplonk_eval_challenge - gemini_eval_challenge).invert() + + shplonk_batching_challenge * (shplonk_eval_challenge + gemini_eval_challenge).invert(); + + Fr shifted_scalar = gemini_eval_challenge.invert() * + ((shplonk_eval_challenge - gemini_eval_challenge).invert() - + shplonk_batching_challenge * (shplonk_eval_challenge + gemini_eval_challenge).invert()); + + ShpleminiVerifier::batch_multivariate_opening_claims(RefVector(unshifted_commitments), + RefVector(shifted_commitments), + RefVector(multilinear_evaluations), + rho, + unshifted_scalar, + shifted_scalar, + commitments, + scalars, + verifier_batched_evaluation); + + // Final pairing check + GroupElement shplemini_result = Utils::batch_mul_native(commitments, scalars); + + EXPECT_EQ(commitments.size(), unshifted_commitments.size() + shifted_commitments.size()); + EXPECT_EQ(batched_evaluation, verifier_batched_evaluation); + EXPECT_EQ(-expected_result, shplemini_result); +} + +TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching) +{ + using GeminiProver = GeminiProver_; + using ShpleminiVerifier = ShpleminiVerifier_; + using ShplonkVerifier = ShplonkVerifier_; + using Fr = typename TypeParam::ScalarField; + using GroupElement = typename TypeParam::Element; + using Commitment = typename TypeParam::AffineElement; + using Polynomial = typename bb::Polynomial; + using Utils = CommitmentSchemesUtils; + + const size_t n = 16; + const size_t log_n = 4; + + // Generate mock challenges + Fr rho = Fr::random_element(); + Fr gemini_eval_challenge = Fr::random_element(); + Fr shplonk_batching_challenge = Fr::random_element(); + Fr shplonk_eval_challenge = Fr::random_element(); + + // Generate multilinear polynomials and compute their commitments + auto mle_opening_point = this->random_evaluation_point(log_n); + auto poly1 = Polynomial::random(n); + auto poly2 = Polynomial::random(n, /*shiftable*/ 1); + Polynomial poly3 = Polynomial::shiftable(n); + + // Evaluate the polynomials at the multivariate challenge, poly3 is not evaluated, because it is 0. + auto eval1 = poly1.evaluate_mle(mle_opening_point); + auto eval2 = poly2.evaluate_mle(mle_opening_point); + Fr eval3{ 0 }; + Fr eval3_shift{ 0 }; + auto eval2_shift = poly2.evaluate_mle(mle_opening_point, true); + + // Collect multilinear evaluations + std::vector multilinear_evaluations = { eval1, eval2, eval3, eval2_shift, eval3_shift }; + std::vector rhos = gemini::powers_of_rho(rho, multilinear_evaluations.size()); + + Polynomial batched_unshifted(n); + Polynomial batched_to_be_shifted = Polynomial::shiftable(n); + batched_unshifted.add_scaled(poly1, rhos[0]); + batched_unshifted.add_scaled(poly2, rhos[1]); + batched_unshifted.add_scaled(poly3, rhos[2]); + batched_to_be_shifted.add_scaled(poly2, rhos[3]); + batched_to_be_shifted.add_scaled(poly3, rhos[4]); + + // Compute: + // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1 + // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1 + auto gemini_polynomials = GeminiProver::compute_gemini_polynomials( + mle_opening_point, std::move(batched_unshifted), std::move(batched_to_be_shifted)); + + std::vector prover_commitments; + for (size_t l = 0; l < log_n - 1; ++l) { + auto commitment = this->ck()->commit(gemini_polynomials[l + 2]); + prover_commitments.emplace_back(commitment); + } + + const auto [gemini_opening_pairs, gemini_witnesses] = GeminiProver::compute_fold_polynomial_evaluations( + mle_opening_point, std::move(gemini_polynomials), gemini_eval_challenge); + + std::vector prover_evaluations; + std::vector> opening_claims; + for (size_t l = 0; l < log_n; ++l) { + const auto& evaluation = gemini_opening_pairs[l + 1].evaluation; + prover_evaluations.emplace_back(evaluation); + } + + std::vector r_squares = gemini::powers_of_evaluation_challenge(gemini_eval_challenge, log_n); + + GroupElement expected_result = GroupElement::zero(); + std::vector expected_inverse_vanishing_evals(log_n + 1); + // Compute expected inverses + expected_inverse_vanishing_evals[0] = (shplonk_eval_challenge - r_squares[0]).invert(); + expected_inverse_vanishing_evals[1] = (shplonk_eval_challenge + r_squares[0]).invert(); + expected_inverse_vanishing_evals[2] = (shplonk_eval_challenge + r_squares[1]).invert(); + expected_inverse_vanishing_evals[3] = (shplonk_eval_challenge + r_squares[2]).invert(); + expected_inverse_vanishing_evals[4] = (shplonk_eval_challenge + r_squares[3]).invert(); + + Fr current_challenge{ shplonk_batching_challenge * shplonk_batching_challenge }; + for (size_t idx = 0; idx < prover_commitments.size(); ++idx) { + expected_result -= prover_commitments[idx] * current_challenge * expected_inverse_vanishing_evals[idx + 2]; + current_challenge *= shplonk_batching_challenge; + } + + // Run the ShepliminiVerifier batching method + std::vector inverse_vanishing_evals = + ShplonkVerifier::compute_inverted_gemini_denominators(log_n + 1, shplonk_eval_challenge, r_squares); + + std::vector commitments; + std::vector scalars; + Fr expected_constant_term_accumulator{ 0 }; + + ShpleminiVerifier::batch_gemini_claims_received_from_prover(log_n, + prover_commitments, + prover_evaluations, + inverse_vanishing_evals, + shplonk_batching_challenge, + commitments, + scalars, + expected_constant_term_accumulator); + + EXPECT_EQ(commitments.size(), prover_commitments.size()); + // Compute the group element using the output of Shplemini method + GroupElement shplemini_result = Utils::batch_mul_native(commitments, scalars); + + EXPECT_EQ(shplemini_result, expected_result); +} +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp index 9eac7b4a48c..5526feca2c3 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp @@ -54,7 +54,7 @@ template class ShplonkProver_ { // Compute individual claim quotient tmp = ( fⱼ(X) − vⱼ) / ( X − xⱼ ) tmp = claim.polynomial; - tmp[0] -= claim.opening_pair.evaluation; + tmp.at(0) = tmp[0] - claim.opening_pair.evaluation; tmp.factor_roots(claim.opening_pair.challenge); // Add the claim quotient to the batched quotient polynomial @@ -103,7 +103,7 @@ template class ShplonkProver_ { for (const auto& claim : opening_claims) { // tmp = ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ ) tmp = claim.polynomial; - tmp[0] -= claim.opening_pair.evaluation; + tmp.at(0) = tmp[0] - claim.opening_pair.evaluation; Fr scaling_factor = current_nu * inverse_vanishing_evals[idx]; // = ρʲ / ( r − xⱼ ) // G -= ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ ) @@ -268,5 +268,25 @@ template class ShplonkVerifier_ { // Return opening pair (z, 0) and commitment [G] return { { z_challenge, Fr(0) }, G_commitment }; }; + /** + * @brief Computes \f$ \frac{1}{z - r}, \frac{1}{z+r}, \ldots, \frac{1}{z+r^{2^{d-1}}} \f$. + * + * @param log_circuit_size \f$ d \f$ + * @param shplonk_eval_challenge \f$ z \f$ + * @param gemini_eval_challenge_powers \f$ (r , r^2, \ldots, r^{2^{d-1}}) \f$ + * @return \f[ \left( \frac{1}{z - r}, \frac{1}{z+r}, \ldots, \frac{1}{z+r^{2^{d-1}}} \right) \f] + */ + static std::vector compute_inverted_gemini_denominators(const size_t num_gemini_claims, + const Fr& shplonk_eval_challenge, + const std::vector& gemini_eval_challenge_powers) + { + std::vector inverted_denominators; + inverted_denominators.reserve(num_gemini_claims); + inverted_denominators.emplace_back((shplonk_eval_challenge - gemini_eval_challenge_powers[0]).invert()); + for (const auto& gemini_eval_challenge_power : gemini_eval_challenge_powers) { + inverted_denominators.emplace_back((shplonk_eval_challenge + gemini_eval_challenge_power).invert()); + } + return inverted_denominators; + } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.test.cpp index 73e726ed34c..52bd9017e18 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.test.cpp @@ -1,14 +1,12 @@ #include "shplonk.hpp" +#include "../commitment_key.test.hpp" #include "../gemini/gemini.hpp" - +#include "barretenberg/commitment_schemes/claim.hpp" #include #include #include #include #include - -#include "../commitment_key.test.hpp" -#include "barretenberg/commitment_schemes/claim.hpp" namespace bb { template class ShplonkTest : public CommitmentTest {}; @@ -32,12 +30,12 @@ TYPED_TEST(ShplonkTest, ShplonkSimple) // Generate two random (unrelated) polynomials of two different sizes, as well as their evaluations at a (single but // different) random point and their commitments. const auto r1 = Fr::random_element(); - auto poly1 = this->random_polynomial(n); + auto poly1 = Polynomial::random(n); const auto eval1 = poly1.evaluate(r1); const auto commitment1 = this->commit(poly1); const auto r2 = Fr::random_element(); - auto poly2 = this->random_polynomial(n / 2); + auto poly2 = Polynomial::random(n / 2); const auto eval2 = poly2.evaluate(r2); const auto commitment2 = this->commit(poly2); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/sparse_commitment.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/sparse_commitment.test.cpp index f555d437d08..9d7da38d893 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/sparse_commitment.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/sparse_commitment.test.cpp @@ -55,7 +55,7 @@ TYPED_TEST(CommitmentKeyTest, CommitSparse) Polynomial poly{ num_points }; for (size_t i = 0; i < num_nonzero; ++i) { size_t idx = (i + 1) * (i + 1) % num_points; - poly[idx] = Fr::random_element(); + poly.at(idx) = Fr::random_element(); } // Commit to the polynomial using both the conventional commit method and the sparse commitment method diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/batch_mul_native.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/batch_mul_native.hpp new file mode 100644 index 00000000000..59970ea6d0b --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/utils/batch_mul_native.hpp @@ -0,0 +1,43 @@ +#pragma once +#include "barretenberg/common/ref_span.hpp" +#include "barretenberg/stdlib/primitives/biggroup/biggroup.hpp" +#include + +namespace bb { +template class CommitmentSchemesUtils { + + public: + using Commitment = typename Curve::AffineElement; + using FF = typename Curve::ScalarField; + + /** + * @brief Utility for native batch multiplication of group elements + * @note This is used only for native verification and is not optimized for efficiency + */ + static Commitment batch_mul_native(const std::vector& _points, const std::vector& _scalars) + { + std::vector points; + std::vector scalars; + for (size_t i = 0; i < _points.size(); ++i) { + const auto& point = _points[i]; + const auto& scalar = _scalars[i]; + + // TODO: Special handling of point at infinity here due to incorrect serialization. + if (!scalar.is_zero() && !point.is_point_at_infinity() && !point.y.is_zero()) { + points.emplace_back(point); + scalars.emplace_back(scalar); + } + } + + if (points.empty()) { + return Commitment::infinity(); + } + + auto result = points[0] * scalars[0]; + for (size_t idx = 1; idx < scalars.size(); ++idx) { + result = result + points[idx] * scalars[idx]; + } + return result; + } +}; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp index c5ed65abc86..25b31bece47 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp @@ -34,6 +34,7 @@ template <> class VerifierCommitmentKey { using Commitment = typename Curve::AffineElement; VerifierCommitmentKey() { srs = srs::get_crs_factory()->get_verifier_crs(); }; + bool operator==(const VerifierCommitmentKey&) const = default; Commitment get_g1_identity() { return srs->get_g1_identity(); } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp index aa0cf5b0273..659fa2be271 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp @@ -1,7 +1,9 @@ #pragma once #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/commitment_schemes/utils/batch_mul_native.hpp" #include "barretenberg/commitment_schemes/verification_key.hpp" +#include "barretenberg/common/debug_log.hpp" #include "barretenberg/common/ref_span.hpp" #include "barretenberg/common/ref_vector.hpp" #include "barretenberg/common/zip_view.hpp" @@ -70,6 +72,7 @@ template class ZeroMorphProver_ { static std::vector compute_multilinear_quotients(Polynomial& polynomial, std::span u_challenge) { + DEBUG_LOG(polynomial, u_challenge); size_t log_N = numeric::get_msb(polynomial.size()); // Define the vector of quotients q_k, k = 0, ..., log_N-1 std::vector quotients; @@ -82,10 +85,11 @@ template class ZeroMorphProver_ { size_t size_q = 1 << (log_N - 1); Polynomial q{ size_q }; for (size_t l = 0; l < size_q; ++l) { - q[l] = polynomial[size_q + l] - polynomial[l]; + q.at(l) = polynomial[size_q + l] - polynomial[l]; } quotients[log_N - 1] = q.share(); + DEBUG_LOG(quotients[log_N - 1], log_N - 1); std::vector f_k; f_k.resize(size_q); @@ -103,7 +107,7 @@ template class ZeroMorphProver_ { q = Polynomial{ size_q }; for (size_t l = 0; l < size_q; ++l) { - q[l] = f_k[size_q + l] - f_k[l]; + q.at(l) = f_k[size_q + l] - f_k[l]; } quotients[log_N - k - 1] = q.share(); @@ -129,6 +133,7 @@ template class ZeroMorphProver_ { FF y_challenge, size_t N) { + DEBUG_LOG(quotients, y_challenge, N); // Batched lifted degree quotient polynomial auto result = Polynomial(N); @@ -141,7 +146,7 @@ template class ZeroMorphProver_ { auto deg_k = static_cast((1 << k) - 1); size_t offset = N - deg_k - 1; for (size_t idx = 0; idx < deg_k + 1; ++idx) { - result[offset + idx] += scalar * quotient[idx]; + result.at(offset + idx) += scalar * quotient[idx]; } scalar *= y_challenge; // update batching scalar y^k k++; @@ -167,6 +172,7 @@ template class ZeroMorphProver_ { FF y_challenge, FF x_challenge) { + DEBUG_LOG(batched_quotient, quotients, y_challenge, x_challenge); size_t N = batched_quotient.size(); size_t log_N = quotients.size(); @@ -216,17 +222,20 @@ template class ZeroMorphProver_ { FF x_challenge, std::vector concatenation_groups_batched = {}) { + DEBUG_LOG( + f_batched, g_batched, quotients, v_evaluation, u_challenge, x_challenge, concatenation_groups_batched); size_t N = f_batched.size(); size_t log_N = quotients.size(); // Initialize Z_x with x * \sum_{i=0}^{m-1} f_i + \sum_{i=0}^{l-1} g_i - auto result = g_batched; + // Make sure g_batched does not have any starting implicit/virtual 0s as we will assign to [0] + auto result = g_batched.full(); result.add_scaled(f_batched, x_challenge); // Compute Z_x -= v * x * \Phi_n(x) auto phi_numerator = x_challenge.pow(N) - 1; // x^N - 1 auto phi_n_x = phi_numerator / (x_challenge - 1); - result[0] -= v_evaluation * x_challenge * phi_n_x; + result.at(0) -= v_evaluation * x_challenge * phi_n_x; // Add contribution from q_k polynomials auto x_power = x_challenge; // x^{2^k} @@ -287,6 +296,7 @@ template class ZeroMorphProver_ { Polynomial& Z_x, FF z_challenge) { + DEBUG_LOG(zeta_x, Z_x, z_challenge); // We cannot commit to polynomials with size > N_max size_t N = zeta_x.size(); ASSERT(N <= N_max); @@ -335,6 +345,15 @@ template class ZeroMorphProver_ { RefSpan concatenated_evaluations = {}, const std::vector>& concatenation_groups = {}) { + DEBUG_LOG(f_polynomials, + g_polynomials, + g_shift_evaluations, + multilinear_challenge, + commitment_key, + transcript, + concatenated_polynomials, + concatenated_evaluations, + concatenation_groups); // Generate batching challenge \rho and powers 1,...,\rho^{m-1} const FF rho = transcript->template get_challenge("rho"); @@ -358,7 +377,7 @@ template class ZeroMorphProver_ { batching_scalar *= rho; } - Polynomial g_batched{ N }; // batched to-be-shifted polynomials + Polynomial g_batched{ N - 1, N, 1 }; // batched to-be-shifted polynomials for (auto [g_poly, g_shift_eval] : zip_view(g_polynomials, g_shift_evaluations)) { g_batched.add_scaled(g_poly, batching_scalar); batched_evaluation += batching_scalar * g_shift_eval; @@ -397,6 +416,7 @@ template class ZeroMorphProver_ { // Compute and send commitments C_{q_k} = [q_k], k = 0,...,d-1 for (size_t idx = 0; idx < log_N; ++idx) { Commitment q_k_commitment = commitment_key->commit(quotients[idx]); + DEBUG_LOG(idx, quotients[idx], q_k_commitment); std::string label = "ZM:C_q_" + std::to_string(idx); transcript->send_to_verifier(label, q_k_commitment); } @@ -449,6 +469,7 @@ template class ZeroMorphProver_ { template class ZeroMorphVerifier_ { using FF = typename Curve::ScalarField; using Commitment = typename Curve::AffineElement; + using Utils = CommitmentSchemesUtils; public: /** @@ -528,7 +549,7 @@ template class ZeroMorphVerifier_ { return Commitment::batch_mul(commitments, scalars); } } else { - return batch_mul_native(commitments, scalars); + return Utils::batch_mul_native(commitments, scalars); } } @@ -684,38 +705,10 @@ template class ZeroMorphVerifier_ { return Commitment::batch_mul(commitments, scalars); } } else { - return batch_mul_native(commitments, scalars); + return Utils::batch_mul_native(commitments, scalars); } } - /** - * @brief Utility for native batch multiplication of group elements - * @note This is used only for native verification and is not optimized for efficiency - */ - static Commitment batch_mul_native(const std::vector& _points, const std::vector& _scalars) - { - std::vector points; - std::vector scalars; - for (auto [point, scalar] : zip_view(_points, _scalars)) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/866) Special handling of point at infinity here - // due to incorrect serialization. - if (!scalar.is_zero() && !point.is_point_at_infinity() && !point.y.is_zero()) { - points.emplace_back(point); - scalars.emplace_back(scalar); - } - } - - if (points.empty()) { - return Commitment::infinity(); - } - - auto result = points[0] * scalars[0]; - for (size_t idx = 1; idx < scalars.size(); ++idx) { - result = result + points[idx] * scalars[idx]; - } - return result; - } - /** * @brief Return the univariate opening claim used to verify, in a subsequent PCS, a set of multilinear evaluation * claims for unshifted polynomials f_i and to-be-shifted polynomials g_i diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp index 146ce53b461..1f060410679 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp @@ -109,8 +109,7 @@ template class ZeroMorphTest : public CommitmentTest f_commitments; size_t poly_length = 1 << u_challenge.size(); for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_polynomials.emplace_back(this->random_polynomial(poly_length)); - f_polynomials[i][0] = Fr(0); // ensure f is "shiftable" + f_polynomials.emplace_back(Polynomial::random(poly_length, 1)); // ensure f is "shiftable" v_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge)); f_commitments.emplace_back(this->commit(f_polynomials[i])); } @@ -177,8 +176,8 @@ template class ZeroMorphTest : public CommitmentTest 0) { tmp = Fr::random_element(this->engine); } - chunk_polynomial[k] = tmp; - concatenated_polynomial[j * MINI_CIRCUIT_N + k] = tmp; + chunk_polynomial.at(k) = tmp; + concatenated_polynomial.at(j * MINI_CIRCUIT_N + k) = tmp; } concatenation_group.emplace_back(chunk_polynomial); } @@ -333,7 +332,7 @@ TYPED_TEST(ZeroMorphTest, QuotientConstruction) size_t log_N = numeric::get_msb(N); // Construct a random multilinear polynomial f, and (u,v) such that f(u) = v. - Polynomial multilinear_f = this->random_polynomial(N); + Polynomial multilinear_f = Polynomial::random(N); std::vector u_challenge = this->random_evaluation_point(log_N); Fr v_evaluation = multilinear_f.evaluate_mle(u_challenge); @@ -509,9 +508,8 @@ TYPED_TEST(ZeroMorphTest, PartiallyEvaluatedQuotientZ) size_t log_N = numeric::get_msb(N); // Construct a random multilinear polynomial f, and (u,v) such that f(u) = v. - Polynomial multilinear_f = this->random_polynomial(N); - Polynomial multilinear_g = this->random_polynomial(N); - multilinear_g[0] = 0; + Polynomial multilinear_f = Polynomial::random(N); + Polynomial multilinear_g = Polynomial::random(N, /* starting index for shift */ 1); std::vector u_challenge = this->random_evaluation_point(log_N); Fr v_evaluation = multilinear_f.evaluate_mle(u_challenge); Fr w_evaluation = multilinear_g.evaluate_mle(u_challenge, /* shift = */ true); @@ -525,9 +523,9 @@ TYPED_TEST(ZeroMorphTest, PartiallyEvaluatedQuotientZ) auto v_batched = v_evaluation + rho * w_evaluation; // Define some mock q_k with deg(q_k) = 2^k - 1 - auto q_0 = this->random_polynomial(1 << 0); - auto q_1 = this->random_polynomial(1 << 1); - auto q_2 = this->random_polynomial(1 << 2); + auto q_0 = Polynomial::random(1 << 0); + auto q_1 = Polynomial::random(1 << 1); + auto q_2 = Polynomial::random(1 << 2); std::vector quotients = { q_0, q_1, q_2 }; auto x_challenge = Fr::random_element(); @@ -537,9 +535,10 @@ TYPED_TEST(ZeroMorphTest, PartiallyEvaluatedQuotientZ) f_batched, g_batched, quotients, v_batched, u_challenge, x_challenge); // Compute Z_x directly - auto Z_x_expected = g_batched; + // Expand g_batched as it has a virtual 0 + auto Z_x_expected = g_batched.full(); Z_x_expected.add_scaled(f_batched, x_challenge); - Z_x_expected[0] -= v_batched * x_challenge * this->Phi(x_challenge, log_N); + Z_x_expected.at(0) -= v_batched * x_challenge * this->Phi(x_challenge, log_N); for (size_t k = 0; k < log_N; ++k) { auto x_pow_2k = x_challenge.pow(1 << k); // x^{2^k} auto x_pow_2kp1 = x_challenge.pow(1 << (k + 1)); // x^{2^{k+1}} diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp new file mode 100644 index 00000000000..f37c2b7b49e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp @@ -0,0 +1,177 @@ +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/commitment_schemes/commitment_key.test.hpp" +#include "barretenberg/commitment_schemes/gemini/gemini.hpp" +#include "barretenberg/commitment_schemes/ipa/ipa.hpp" +#include "barretenberg/commitment_schemes/kzg/kzg.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplemini_verifier.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" +#include "barretenberg/srs/global_crs.hpp" +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib/primitives/curves/grumpkin.hpp" +#include "barretenberg/stdlib/transcript/transcript.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include + +using namespace bb; + +template class ShpleminiRecursionTest : public CommitmentTest {}; + +numeric::RNG& shplemini_engine = numeric::get_debug_randomness(); + +/** + * @brief Test Recursive Verification for 2 multilinear polynomials and a shift of one of them + * + */ +TEST(ShpleminiRecursionTest, ProveAndVerifySingle) +{ + // Define some useful type aliases + using Builder = UltraCircuitBuilder; + using Curve = typename stdlib::bn254; + using NativeCurve = typename Curve::NativeCurve; + using Commitment = typename Curve::AffineElement; + using NativeCommitment = typename Curve::AffineElementNative; + using NativeCurve = typename Curve::NativeCurve; + using NativePCS = std::conditional_t, KZG, IPA>; + using CommitmentKey = typename NativePCS::CK; + using GeminiProver = GeminiProver_; + using ShplonkProver = ShplonkProver_; + using ShpleminiVerifier = ShpleminiVerifier_; + using Fr = typename Curve::ScalarField; + using NativeFr = typename Curve::NativeCurve::ScalarField; + using Polynomial = bb::Polynomial; + using Transcript = bb::BaseTranscript>; + + constexpr size_t N = 16; + constexpr size_t log_circuit_size = 4; + constexpr size_t NUM_UNSHIFTED = 2; + constexpr size_t NUM_SHIFTED = 1; + + srs::init_crs_factory("../srs_db/ignition"); + + std::vector u_challenge(log_circuit_size); + for (size_t idx = 0; idx < log_circuit_size; ++idx) { + u_challenge[idx] = NativeFr::random_element(&shplemini_engine); + }; + // Construct some random multilinear polynomials f_i and their evaluations v_i = f_i(u) + std::vector f_polynomials; // unshifted polynomials + std::vector v_evaluations; + for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { + f_polynomials.emplace_back(Polynomial::random(N, /*shiftable*/ 1)); + v_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge)); + } + + // Construct some "shifted" multilinear polynomials h_i as the left-shift-by-1 of f_i + std::vector g_polynomials; // to-be-shifted polynomials + std::vector h_polynomials; // shifts of the to-be-shifted polynomials + std::vector w_evaluations; + if constexpr (NUM_SHIFTED > 0) { + for (size_t i = 0; i < NUM_SHIFTED; ++i) { + g_polynomials.emplace_back(f_polynomials[i]); + h_polynomials.emplace_back(g_polynomials[i].shifted()); + w_evaluations.emplace_back(h_polynomials[i].evaluate_mle(u_challenge)); + } + } + + std::vector claimed_evaluations; + claimed_evaluations.reserve(v_evaluations.size() + w_evaluations.size()); + claimed_evaluations.insert(claimed_evaluations.end(), v_evaluations.begin(), v_evaluations.end()); + claimed_evaluations.insert(claimed_evaluations.end(), w_evaluations.begin(), w_evaluations.end()); + // Compute commitments [f_i] + std::vector f_commitments; + auto commitment_key = std::make_shared(4096); + for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { + f_commitments.emplace_back(commitment_key->commit(f_polynomials[i])); + } + // Construct container of commitments of the "to-be-shifted" polynomials [g_i] (= [f_i]) + std::vector g_commitments; + for (size_t i = 0; i < NUM_SHIFTED; ++i) { + g_commitments.emplace_back(f_commitments[i]); + } + + // Initialize an empty NativeTranscript + auto prover_transcript = NativeTranscript::prover_init_empty(); + + NativeFr rho = prover_transcript->template get_challenge("rho"); + std::vector rhos = gemini::powers_of_rho(rho, NUM_SHIFTED + NUM_UNSHIFTED); + // Batch the unshifted polynomials and the to-be-shifted polynomials using ρ + Polynomial batched_poly_unshifted(N); + size_t poly_idx = 0; + for (auto& unshifted_poly : f_polynomials) { + batched_poly_unshifted.add_scaled(unshifted_poly, rhos[poly_idx]); + ++poly_idx; + } + + Polynomial batched_poly_to_be_shifted = Polynomial::shiftable(N); // batched to-be-shifted polynomials + for (auto& to_be_shifted_poly : g_polynomials) { + batched_poly_to_be_shifted.add_scaled(to_be_shifted_poly, rhos[poly_idx]); + ++poly_idx; + }; + + // Compute d-1 polynomials Fold^(i), i = 1, ..., d-1. + auto fold_polynomials = GeminiProver::compute_gemini_polynomials( + u_challenge, std::move(batched_poly_unshifted), std::move(batched_poly_to_be_shifted)); + // Comute and add to trasnscript the commitments [Fold^(i)], i = 1, ..., d-1 + for (size_t l = 0; l < log_circuit_size - 1; ++l) { + NativeCommitment current_commitment = commitment_key->commit(fold_polynomials[l + 2]); + prover_transcript->send_to_verifier("Gemini:FOLD_" + std::to_string(l + 1), current_commitment); + } + const NativeFr r_challenge = prover_transcript->template get_challenge("Gemini:r"); + + const auto [gemini_opening_pairs, gemini_witnesses] = + GeminiProver::compute_fold_polynomial_evaluations(u_challenge, std::move(fold_polynomials), r_challenge); + + std::vector> opening_claims; + for (size_t l = 0; l < log_circuit_size; ++l) { + std::string label = "Gemini:a_" + std::to_string(l); + const auto& evaluation = gemini_opening_pairs[l + 1].evaluation; + prover_transcript->send_to_verifier(label, evaluation); + opening_claims.emplace_back(gemini_witnesses[l], gemini_opening_pairs[l]); + } + opening_claims.emplace_back(gemini_witnesses[log_circuit_size], gemini_opening_pairs[log_circuit_size]); + + // Shplonk prover output: + // - opening pair: (z_challenge, 0) + // - witness: polynomial Q - Q_z + ShplonkProver::prove(commitment_key, opening_claims, prover_transcript); + + Builder builder; + StdlibProof stdlib_proof = bb::convert_proof_to_witness(&builder, prover_transcript->proof_data); + auto stdlib_verifier_transcript = std::make_shared(stdlib_proof); + [[maybe_unused]] auto _ = stdlib_verifier_transcript->template receive_from_prover("Init"); + + // Execute Verifier protocol without the need for vk prior the final check + const auto commitments_to_witnesses = [&builder](const auto& commitments) { + std::vector commitments_in_biggroup(commitments.size()); + std::transform(commitments.begin(), + commitments.end(), + commitments_in_biggroup.begin(), + [&builder](const auto& native_commitment) { + return Commitment::from_witness(&builder, native_commitment); + }); + return commitments_in_biggroup; + }; + const auto elements_to_witness = [&](const auto& elements) { + std::vector elements_in_circuit(elements.size()); + std::transform(elements.begin(), + elements.end(), + elements_in_circuit.begin(), + [&builder](const auto& native_element) { return Fr::from_witness(&builder, native_element); }); + return elements_in_circuit; + }; + auto stdlib_f_commitments = commitments_to_witnesses(f_commitments); + auto stdlib_g_commitments = commitments_to_witnesses(g_commitments); + auto stdlib_claimed_evaluations = elements_to_witness(claimed_evaluations); + + std::vector u_challenge_in_circuit = elements_to_witness(u_challenge); + + [[maybe_unused]] auto opening_claim = + ShpleminiVerifier::compute_batch_opening_claim(Fr::from_witness(&builder, log_circuit_size), + RefVector(stdlib_f_commitments), + RefVector(stdlib_g_commitments), + RefVector(stdlib_claimed_evaluations), + u_challenge_in_circuit, + Commitment::one(&builder), + stdlib_verifier_transcript); + + EXPECT_TRUE(CircuitChecker::check(builder)); +} diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp index 322f589a600..a31be135de5 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp @@ -10,8 +10,6 @@ #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" #include -#include - using namespace bb; template class ZeroMorphRecursionTest : public CommitmentTest {}; @@ -40,31 +38,34 @@ TEST(ZeroMorphRecursionTest, ProveAndVerifySingle) using ZeroMorphVerifier = ZeroMorphVerifier_; using Transcript = bb::BaseTranscript>; - constexpr size_t N = 2; - constexpr size_t NUM_UNSHIFTED = 1; - constexpr size_t NUM_SHIFTED = 0; + constexpr size_t N = 8; + constexpr size_t LOG_N = 3; + constexpr size_t NUM_UNSHIFTED = 2; + constexpr size_t NUM_SHIFTED = 1; srs::init_crs_factory("../srs_db/ignition"); - - std::vector u_challenge = { NativeFr::random_element(&engine) }; + std::vector u_challenge(LOG_N); + for (size_t idx = 0; idx < LOG_N; ++idx) { + u_challenge[idx] = NativeFr::random_element(&engine); + }; // Construct some random multilinear polynomials f_i and their evaluations v_i = f_i(u) std::vector f_polynomials; // unshifted polynomials std::vector v_evaluations; for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_polynomials.emplace_back(Polynomial::random(N)); - f_polynomials[i][0] = NativeFr(0); // ensure f is "shiftable" + f_polynomials.emplace_back(Polynomial::random(N, /* starting index for shift */ 1)); v_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge)); } - // Construct some "shifted" multilinear polynomials h_i as the left-shift-by-1 of f_i std::vector g_polynomials; // to-be-shifted polynomials std::vector h_polynomials; // shifts of the to-be-shifted polynomials std::vector w_evaluations; - for (size_t i = 0; i < NUM_SHIFTED; ++i) { - g_polynomials.emplace_back(f_polynomials[i]); - h_polynomials.emplace_back(g_polynomials[i].shifted()); - w_evaluations.emplace_back(h_polynomials[i].evaluate_mle(u_challenge)); + if constexpr (NUM_SHIFTED > 0) { + for (size_t i = 0; i < NUM_SHIFTED; ++i) { + g_polynomials.emplace_back(f_polynomials[i]); + h_polynomials.emplace_back(g_polynomials[i].shifted()); + w_evaluations.emplace_back(h_polynomials[i].evaluate_mle(u_challenge)); + } } // Compute commitments [f_i] diff --git a/barretenberg/cpp/src/barretenberg/common/debug_log.cpp b/barretenberg/cpp/src/barretenberg/common/debug_log.cpp new file mode 100644 index 00000000000..c97ca6561a2 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/common/debug_log.cpp @@ -0,0 +1,18 @@ +#include "debug_log.hpp" +#include +#include +#include +#ifdef BBERG_DEBUG_LOG +namespace barretenberg { +void _debug_log_impl(const std::string& log_str) +{ + const char* abort_cond = std::getenv("DEBUG_LOG_ABORT"); + if (abort_cond != nullptr && log_str.find(abort_cond) != std::string::npos) { + throw std::runtime_error("Abort condition met: " + log_str); + } + if (abort_cond == nullptr) { + std::cout << log_str << std::endl; + } +} +} // namespace barretenberg +#endif diff --git a/barretenberg/cpp/src/barretenberg/common/debug_log.hpp b/barretenberg/cpp/src/barretenberg/common/debug_log.hpp new file mode 100644 index 00000000000..ef06822249f --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/common/debug_log.hpp @@ -0,0 +1,108 @@ +#pragma once + +/** + * @details + * To be used to create a verbose trace of execution. This helps with comparing runs that should have had the same + * result, but don't. It is less useful for other kinds of correctness, but if we know what values we expect (or not) it + * still can be useful. + * + * Compilation: cmake -DCMAKE_CXX_FLAGS="-DBBERG_DEBUG_LOG" ... + * Then, compare outputs of the program with another run of the same program (it's good to remove sources of randomness, + * if present). Once you have a divergence you can use the environment variable DEBUG_LOG_ABORT=... with a string + * pattern to abort the program, stopping in a debugger. + */ + +#ifdef BBERG_DEBUG_LOG + +#include +#include +#include +namespace barretenberg { +/** + * Throws an std::runtime_error if we would print a log that includes the env variable DEBUG_LOG_ABORT. + * This is primarily intended to be used with a debugger to then poke around execution and see differences in a + * comparison log. Prints the string if DEBUG_LOG_ABORT is not set. + * Should be run with MULTITHREADING=OFF if DEBUG_LOG is used within parallel_for, and with as little non-determinism as + * possible (the BBERG_DEBUG_LOG flag currently turns off some determinism). + * @param log_str The log string to be checked against the environment variable. + */ +void _debug_log_impl(const std::string& log_str); + +template +concept Printable = requires(T a) { std::cout << a; }; +template +concept ContainerLike = requires(T a) { + a.begin(); + a.size(); +}; + +template const char* _summarize(const T* /*unused*/) +{ + return "(?)"; +} + +template const T& _summarize(const T* x) +{ + return *x; +} + +// fallback for non-printable containers +template +std::string _summarize(const T* x) + requires(!Printable) +{ + std::ostringstream ss; + if (x->size() == 0) { + ss << "[]"; + } else { + ss << "[" << _summarize(&*x->begin()) << "...]"; + } + return ss.str(); +} + +/** + * Logs multiple values to standard output. + * + * @param args The values to be logged. + */ +template void _debug_log(const char* func_name, const char* arg_string, const FuncArgs&... args) +{ + // shut off recursive DEBUG_LOG + static size_t debug_log_calls = 0; + if (debug_log_calls > 0) { + return; + } + debug_log_calls++; + std::ostringstream ss; + ss << func_name << " " << arg_string << " = "; + // Using fold expression to append args to stringstream + ((ss << _summarize(&args) << " "), ...); + std::string log_str = ss.str(); + // Want to be able to catch offending statements in a debugger, this throws if we match an env variable pattern + _debug_log_impl(log_str); + debug_log_calls--; +} +} // namespace barretenberg +/** + * Logs function parameters. This macro should be placed at the beginning of function + * bodies to log their parameters. + * + * @param ... The parameters to be logged. + */ +#define DEBUG_LOG(...) \ + if (!std::is_constant_evaluated()) { /*we are not in a compile-time constexpr*/ \ + barretenberg::_debug_log(__FUNCTION__, #__VA_ARGS__, __VA_ARGS__); \ + } + +#define DEBUG_LOG_ALL(container) \ + for (auto& x : (container)) { \ + barretenberg::_debug_log(__FUNCTION__, #container, x); \ + } + +#else // If BBERG_DEBUG_LOG is not defined + +// Define empty macros and functions +#define DEBUG_LOG(...) +#define DEBUG_LOG_ALL(container) + +#endif // BBERG_DEBUG_LOG diff --git a/barretenberg/cpp/src/barretenberg/common/log.cpp b/barretenberg/cpp/src/barretenberg/common/log.cpp index 68493a66abb..94ff4f0045a 100644 --- a/barretenberg/cpp/src/barretenberg/common/log.cpp +++ b/barretenberg/cpp/src/barretenberg/common/log.cpp @@ -1,5 +1,12 @@ // Used for `vinfo` in log.hpp. +#include +#include + +#ifndef __wasm__ +bool verbose_logging = std::getenv("BB_VERBOSE") == nullptr ? false : std::string(std::getenv("BB_VERBOSE")) == "1"; +#else bool verbose_logging = false; +#endif // Used for `debug` in log.hpp. bool debug_logging = false; \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/common/ref_vector.hpp b/barretenberg/cpp/src/barretenberg/common/ref_vector.hpp index c74d1b52c19..850053110d2 100644 --- a/barretenberg/cpp/src/barretenberg/common/ref_vector.hpp +++ b/barretenberg/cpp/src/barretenberg/common/ref_vector.hpp @@ -148,4 +148,4 @@ template static std::vector> to_vector_of_ref_vectors( } return result; } -} // namespace bb \ No newline at end of file +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/common/throw_or_abort.hpp b/barretenberg/cpp/src/barretenberg/common/throw_or_abort.hpp index bb140d8761b..f221855ef63 100644 --- a/barretenberg/cpp/src/barretenberg/common/throw_or_abort.hpp +++ b/barretenberg/cpp/src/barretenberg/common/throw_or_abort.hpp @@ -2,12 +2,17 @@ #include "log.hpp" #include +inline void abort_with_message [[noreturn]] (std::string const& err) +{ + info("abort: ", err); + std::abort(); +} + inline void throw_or_abort [[noreturn]] (std::string const& err) { #ifndef __wasm__ throw std::runtime_error(err); #else - info("abort: ", err); - std::abort(); + abort_with_message(err); #endif } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/common/zip_view.hpp b/barretenberg/cpp/src/barretenberg/common/zip_view.hpp index 964888ac644..588e0703cd8 100644 --- a/barretenberg/cpp/src/barretenberg/common/zip_view.hpp +++ b/barretenberg/cpp/src/barretenberg/common/zip_view.hpp @@ -122,9 +122,15 @@ class zip_iterator { T iter, iter_end; std::size_t index = 0; + // This indirection over std::ref fixes iota_view() and other non-reference containers + static auto ref(const auto& t) { return std::ref(t); } + static auto ref(auto& t) { return std::ref(t); } + // We don't forward any reference if we have a value type + static auto ref(const auto&& t) { return t; } + static auto ref(auto&& t) { return t; } template auto get_refs(T t, std::index_sequence) const { - return std::make_tuple(std::ref(*std::get(t))...); + return std::make_tuple(ref(*std::get(t))...); } template auto apply2_impl(F&& f, A&& a, A&& b, std::index_sequence) diff --git a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt index 1cd7f441909..dc8acd00b49 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt @@ -2,6 +2,7 @@ # We do not need to bloat barretenberg.wasm with gzip functionality in a browser context as the browser can do this set(DSL_DEPENDENCIES + aztec_ivc plonk ultra_honk client_ivc @@ -14,10 +15,10 @@ set(DSL_DEPENDENCIES stdlib_honk_verifier) if (NOT WASM) - list(APPEND DSL_DEPENDENCIES libdeflate::libdeflate_static) + list(APPEND DSL_DEPENDENCIES libdeflate::libdeflate_static vm) endif() barretenberg_module( dsl ${DSL_DEPENDENCIES} -) +) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/README.md b/barretenberg/cpp/src/barretenberg/dsl/README.md index 9a76586bde5..45d09a1df60 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/README.md +++ b/barretenberg/cpp/src/barretenberg/dsl/README.md @@ -4,7 +4,7 @@ This package adds support to use [ACIR](https://github.com/noir-lang/noir/tree/m ## Serialization Changes -There are two types of breaking serialization changes. One that alters that alters the internal ACIR structure passed to barretenberg, and one that changes how we serialize the buffer passed to barretenberg. +There are two types of breaking serialization changes. One that alters the internal ACIR structure passed to barretenberg, and one that changes how we serialize the buffer passed to barretenberg. 1. Internal Structure Change diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 62e23117c59..ef8ee0eebc7 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -231,10 +231,17 @@ void build_constraints(Builder& builder, if (!constraint_system.honk_recursion_constraints.empty()) { info("WARNING: this circuit contains unhandled honk_recursion_constraints!"); } + if (!constraint_system.avm_recursion_constraints.empty()) { + info("WARNING: this circuit contains unhandled avm_recursion_constraints!"); + } } else { process_plonk_recursion_constraints(builder, constraint_system, has_valid_witness_assignments, gate_counter); process_honk_recursion_constraints(builder, constraint_system, has_valid_witness_assignments, gate_counter); +#ifndef DISABLE_AZTEC_VM + process_avm_recursion_constraints(builder, constraint_system, has_valid_witness_assignments, gate_counter); +#endif + // If the circuit does not itself contain honk recursion constraints but is going to be // proven with honk then recursively verified, add a default aggregation object if (constraint_system.honk_recursion_constraints.empty() && honk_recursion && @@ -335,7 +342,7 @@ void process_plonk_recursion_constraints(Builder& builder, // final recursion output. builder.set_recursive_proof(current_output_aggregation_object); } -}; +} void process_honk_recursion_constraints(Builder& builder, AcirFormat& constraint_system, @@ -370,7 +377,49 @@ void process_honk_recursion_constraints(Builder& builder, // final recursion output. builder.set_recursive_proof(current_aggregation_object); } -}; +} + +// TODO(https://github.com/AztecProtocol/barretenberg/issues/1095): Probably makes sense to aggregate Honk and AVM +// proofs together. +#ifndef DISABLE_AZTEC_VM +void process_avm_recursion_constraints(Builder& builder, + AcirFormat& constraint_system, + bool has_valid_witness_assignments, + GateCounter& gate_counter) +{ + AggregationObjectIndices current_aggregation_object = + stdlib::recursion::init_default_agg_obj_indices(builder); + + // Add recursion constraints + size_t idx = 0; + for (auto& constraint : constraint_system.avm_recursion_constraints) { + current_aggregation_object = create_avm_recursion_constraints( + builder, constraint, current_aggregation_object, has_valid_witness_assignments); + + gate_counter.track_diff(constraint_system.gates_per_opcode, + constraint_system.original_opcode_indices.avm_recursion_constraints.at(idx++)); + } + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1095): The following code will have to be adapted to + // support a circuit with both honk and avm recursion constraints. + + // Now that the circuit has been completely built, we add + // the output aggregation as public inputs. + if (!constraint_system.avm_recursion_constraints.empty()) { + + // First add the output aggregation object as public inputs + // Set the indices as public inputs because they are no longer being + // created in ACIR + for (const auto& idx : current_aggregation_object) { + builder.set_public_input(idx); + } + + // Make sure the verification key records the public input indices of the + // final recursion output. + builder.set_recursive_proof(current_aggregation_object); + } +} +#endif // DISABLE_AZTEC_VM /** * @brief Specialization for creating Ultra circuit from acir constraints and optionally a witness @@ -383,8 +432,8 @@ void process_honk_recursion_constraints(Builder& builder, */ template <> UltraCircuitBuilder create_circuit(AcirFormat& constraint_system, - size_t size_hint, - WitnessVector const& witness, + const size_t size_hint, + const WitnessVector& witness, bool honk_recursion, [[maybe_unused]] std::shared_ptr, bool collect_gates_per_opcode) @@ -411,8 +460,8 @@ UltraCircuitBuilder create_circuit(AcirFormat& constraint_system, */ template <> MegaCircuitBuilder create_circuit(AcirFormat& constraint_system, - [[maybe_unused]] size_t size_hint, - WitnessVector const& witness, + [[maybe_unused]] const size_t size_hint, + const WitnessVector& witness, bool honk_recursion, std::shared_ptr op_queue, bool collect_gates_per_opcode) @@ -428,6 +477,76 @@ MegaCircuitBuilder create_circuit(AcirFormat& constraint_system, return builder; }; +/** + * @brief Create a kernel circuit from a constraint system and an IVC instance + * @details This method processes ivc_recursion_constraints using the kernel completion logic contained in AztecIvc. + * Since verification keys are known at the time of acir generation, the verification key witnesses contained in the + * constraints are used directly to instantiate the recursive verifiers. On the other hand, the proof witnesses + * contained in the constraints are generally 'dummy' values since proofs are not known during acir generation (with the + * exception of public inputs). This is remedied by connecting the dummy proof witnesses to the genuine proof witnesses, + * known internally to the IVC class, via copy constraints. + * + * @param constraint_system AcirFormat constraint system possibly containing IVC recursion constraints + * @param ivc An IVC instance containing internal data about proofs to be verified + * @param size_hint + * @param witness + * @return MegaCircuitBuilder + */ +MegaCircuitBuilder create_kernel_circuit(AcirFormat& constraint_system, + AztecIVC& ivc, + const WitnessVector& witness, + const size_t size_hint) +{ + using StdlibVerificationKey = AztecIVC::RecursiveVerificationKey; + + // Construct the main kernel circuit logic excluding recursive verifiers + auto circuit = create_circuit(constraint_system, + size_hint, + witness, + /*honk_recursion=*/false, + ivc.goblin.op_queue, + /*collect_gates_per_opcode=*/false); + + // We expect the length of the internal verification queue to match the number of ivc recursion constraints + if (constraint_system.ivc_recursion_constraints.size() != ivc.verification_queue.size()) { + info("WARNING: Mismatch in number of recursive verifications during kernel creation!"); + ASSERT(false); + } + + // Construct a stdlib verification key for each constraint based on the verification key witness indices therein + std::vector> stdlib_verification_keys; + stdlib_verification_keys.reserve(constraint_system.ivc_recursion_constraints.size()); + for (const auto& constraint : constraint_system.ivc_recursion_constraints) { + stdlib_verification_keys.push_back(std::make_shared( + StdlibVerificationKey::from_witness_indices(circuit, constraint.key))); + } + + // Create stdlib representations of each {proof, vkey} pair to be recursively verified + ivc.instantiate_stdlib_verification_queue(circuit, stdlib_verification_keys); + + // Connect the proof/public_input witness indices from each constraint to the corresponding proof witnesses in the + // internal verification queue. This ensures that the witnesses utlized in constraints generated based on acir are + // properly connected to the constraints generated herein via the ivc scheme (e.g. recursive verifications). + for (auto [constraint, queue_entry] : + zip_view(constraint_system.ivc_recursion_constraints, ivc.stdlib_verification_queue)) { + + // Reconstruct complete proof indices from acir constraint data (in which proof is stripped of public inputs) + std::vector complete_proof_indices = + ProofSurgeon::create_indices_for_reconstructed_proof(constraint.proof, constraint.public_inputs); + ASSERT(complete_proof_indices.size() == queue_entry.proof.size()); + + // Assert equality between the proof indices from the constraint data and those of the internal proof + for (auto [proof_value, proof_idx] : zip_view(queue_entry.proof, complete_proof_indices)) { + circuit.assert_equal(proof_value.get_witness_index(), proof_idx); + } + } + + // Complete the kernel circuit with all required recursive verifications, databus consistency checks etc. + ivc.complete_kernel_circuit_logic(circuit); + + return circuit; +}; + template void build_constraints(MegaCircuitBuilder&, AcirFormat&, bool, bool, bool); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index a43c4fa2648..ef80b59020e 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -1,5 +1,11 @@ #pragma once #include "aes128_constraint.hpp" + +#ifndef DISABLE_AZTEC_VM +#include "avm_recursion_constraint.hpp" +#endif + +#include "barretenberg/aztec_ivc/aztec_ivc.hpp" #include "barretenberg/common/slab_allocator.hpp" #include "barretenberg/serialize/msgpack.hpp" #include "bigint_constraint.hpp" @@ -50,6 +56,8 @@ struct AcirFormatOriginalOpcodeIndices { std::vector ec_add_constraints; std::vector recursion_constraints; std::vector honk_recursion_constraints; + std::vector avm_recursion_constraints; + std::vector ivc_recursion_constraints; std::vector bigint_from_le_bytes_constraints; std::vector bigint_to_le_bytes_constraints; std::vector bigint_operations; @@ -75,6 +83,7 @@ struct AcirFormat { uint32_t num_acir_opcodes; + using PolyTripleConstraint = bb::poly_triple_; std::vector public_inputs; std::vector logic_constraints; @@ -96,6 +105,8 @@ struct AcirFormat { std::vector ec_add_constraints; std::vector recursion_constraints; std::vector honk_recursion_constraints; + std::vector avm_recursion_constraints; + std::vector ivc_recursion_constraints; std::vector bigint_from_le_bytes_constraints; std::vector bigint_to_le_bytes_constraints; std::vector bigint_operations; @@ -104,7 +115,7 @@ struct AcirFormat { // A standard plonk arithmetic constraint, as defined in the poly_triple struct, consists of selector values // for q_M,q_L,q_R,q_O,q_C and indices of three variables taking the role of left, right and output wire // This could be a large vector so use slab allocator, we don't expect the blackbox implementations to be so large. - bb::SlabVector> poly_triple_constraints; + bb::SlabVector poly_triple_constraints; bb::SlabVector> quad_constraints; std::vector block_constraints; @@ -140,6 +151,8 @@ struct AcirFormat { ec_add_constraints, recursion_constraints, honk_recursion_constraints, + avm_recursion_constraints, + ivc_recursion_constraints, poly_triple_constraints, block_constraints, bigint_from_le_bytes_constraints, @@ -190,12 +203,17 @@ struct AcirProgramStack { template Builder create_circuit(AcirFormat& constraint_system, - size_t size_hint = 0, - WitnessVector const& witness = {}, + const size_t size_hint = 0, + const WitnessVector& witness = {}, bool honk_recursion = false, std::shared_ptr op_queue = std::make_shared(), bool collect_gates_per_opcode = false); +MegaCircuitBuilder create_kernel_circuit(AcirFormat& constraint_system, + AztecIVC& ivc, + const WitnessVector& witness = {}, + const size_t size_hint = 0); + template void build_constraints( Builder& builder, @@ -248,7 +266,12 @@ void process_plonk_recursion_constraints(Builder& builder, void process_honk_recursion_constraints(Builder& builder, AcirFormat& constraint_system, bool has_valid_witness_assignments, - bool honk_recursion, GateCounter& gate_counter); +#ifndef DISABLE_AZTEC_VM +void process_avm_recursion_constraints(Builder& builder, + AcirFormat& constraint_system, + GateCounter& gate_counter); +#endif + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp index 5b98fa0e249..64a7fea8a5e 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp @@ -61,6 +61,8 @@ TEST_F(AcirFormatTests, TestASingleConstraintNoPubInputs) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -183,6 +185,8 @@ TEST_F(AcirFormatTests, TestLogicGateFromNoirCircuit) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -263,6 +267,8 @@ TEST_F(AcirFormatTests, TestSchnorrVerifyPass) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -370,6 +376,8 @@ TEST_F(AcirFormatTests, TestSchnorrVerifySmallRange) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -490,6 +498,8 @@ TEST_F(AcirFormatTests, TestVarKeccak) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -570,6 +580,8 @@ TEST_F(AcirFormatTests, TestKeccakPermutation) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -647,6 +659,8 @@ TEST_F(AcirFormatTests, TestCollectsGateCounts) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format_mocks.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format_mocks.cpp index 8055948ff7b..e1240d85e82 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format_mocks.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format_mocks.cpp @@ -22,6 +22,8 @@ acir_format::AcirFormatOriginalOpcodeIndices create_empty_original_opcode_indice .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -92,6 +94,12 @@ void mock_opcode_indices(acir_format::AcirFormat& constraint_system) for (size_t i = 0; i < constraint_system.honk_recursion_constraints.size(); i++) { constraint_system.original_opcode_indices.honk_recursion_constraints.push_back(current_opcode++); } + for (size_t i = 0; i < constraint_system.avm_recursion_constraints.size(); i++) { + constraint_system.original_opcode_indices.avm_recursion_constraints.push_back(current_opcode++); + } + for (size_t i = 0; i < constraint_system.ivc_recursion_constraints.size(); i++) { + constraint_system.original_opcode_indices.ivc_recursion_constraints.push_back(current_opcode++); + } for (size_t i = 0; i < constraint_system.bigint_from_le_bytes_constraints.size(); i++) { constraint_system.original_opcode_indices.bigint_from_le_bytes_constraints.push_back(current_opcode++); } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp index 0fb92a275d6..c42ba62db64 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp @@ -1,5 +1,6 @@ #include "acir_to_constraint_buf.hpp" #include "barretenberg/common/container.hpp" +#include "barretenberg/dsl/acir_format/recursion_constraint.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/plonk_honk_shared/arithmetization/gate_data.hpp" #include @@ -466,8 +467,8 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1074): Eventually arg.proof_type will be // the only means for setting the proof type. use of honk_recursion flag in this context can go away // once all noir programs (e.g. protocol circuits) are updated to use the new pattern. - if (honk_recursion && proof_type_in != HONK_RECURSION) { - proof_type_in = HONK_RECURSION; + if (honk_recursion && proof_type_in != HONK && proof_type_in != AVM) { + proof_type_in = HONK; } auto c = RecursionConstraint{ @@ -477,14 +478,22 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, .key_hash = input_key, .proof_type = proof_type_in, }; + // Add the recursion constraint to the appropriate container based on proof type - if (c.proof_type == PLONK_RECURSION) { + switch (c.proof_type) { + case PLONK: af.recursion_constraints.push_back(c); af.original_opcode_indices.recursion_constraints.push_back(opcode_index); - } else if (c.proof_type == HONK_RECURSION) { + break; + case HONK: af.honk_recursion_constraints.push_back(c); af.original_opcode_indices.honk_recursion_constraints.push_back(opcode_index); - } else { + break; + case AVM: + af.avm_recursion_constraints.push_back(c); + af.original_opcode_indices.avm_recursion_constraints.push_back(opcode_index); + break; + default: info("Invalid PROOF_TYPE in RecursionConstraint!"); ASSERT(false); } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.cpp new file mode 100644 index 00000000000..069acda9c57 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.cpp @@ -0,0 +1,197 @@ +#ifndef DISABLE_AZTEC_VM + +#include "avm_recursion_constraint.hpp" +#include "barretenberg/flavor/flavor.hpp" +#include "barretenberg/stdlib/plonk_recursion/aggregation_state/aggregation_state.hpp" +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" +#include "barretenberg/vm/avm/recursion/avm_recursive_flavor.hpp" +#include "barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp" +#include "proof_surgeon.hpp" +#include + +namespace acir_format { + +using namespace bb; +using field_ct = stdlib::field_t; +using bn254 = stdlib::bn254; +using aggregation_state_ct = bb::stdlib::recursion::aggregation_state; + +namespace { +/** + * @brief Creates a dummy vkey and proof object. + * @details Populates the key and proof vectors with dummy values in the write_vk case when we do not have a valid + * witness. The bulk of the logic is setting up certain values correctly like the circuit size, aggregation object, and + * commitments. + * + * @param builder + * @param proof_size Size of proof with NO public inputs + * @param public_inputs_size Total size of public inputs including aggregation object + * @param key_fields + * @param proof_fields + */ +void create_dummy_vkey_and_proof(Builder& builder, + size_t proof_size, + size_t public_inputs_size, + const std::vector& key_fields, + const std::vector& proof_fields) +{ + using Flavor = AvmFlavor; + + size_t num_frs_comm = bb::field_conversion::calc_num_bn254_frs(); + size_t num_frs_fr = bb::field_conversion::calc_num_bn254_frs(); + + // Relevant source for proof layout: AvmFlavor::Transcript::serialize_full_transcript() + assert((proof_size - Flavor::NUM_WITNESS_ENTITIES * num_frs_comm - Flavor::NUM_ALL_ENTITIES * num_frs_fr - + 2 * num_frs_comm) % + (num_frs_comm + num_frs_fr * Flavor::BATCHED_RELATION_PARTIAL_LENGTH) == + 0); + + // Derivation of circuit size based on the proof + // Here, we should always get CONST_PROOF_SIZE_LOG_N which is not what is + // usually set for the AVM proof. As it is a dummy key/proof, it should not matter. + auto log_circuit_size = (proof_size - Flavor::NUM_WITNESS_ENTITIES * num_frs_comm - + Flavor::NUM_ALL_ENTITIES * num_frs_fr - 2 * num_frs_comm) / + (num_frs_comm + num_frs_fr * Flavor::BATCHED_RELATION_PARTIAL_LENGTH); + + /*************************************************************************** + * Construct Dummy Verification Key + ***************************************************************************/ + + // Relevant source for key layout: AvmFlavor::VerificationKey::to_field_elements() + + // First key field is circuit size + builder.assert_equal(builder.add_variable(1 << log_circuit_size), key_fields[0].witness_index); + // Second key field is number of public inputs + builder.assert_equal(builder.add_variable(public_inputs_size), key_fields[1].witness_index); + + size_t offset = 2; + for (size_t i = 0; i < Flavor::NUM_PRECOMPUTED_ENTITIES; ++i) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), key_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), key_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), key_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), key_fields[offset + 3].witness_index); + offset += 4; + } + + /*************************************************************************** + * Construct Dummy Proof + ***************************************************************************/ + + builder.assert_equal(builder.add_variable(1 << log_circuit_size), proof_fields[0].witness_index); + offset = 1; + + // Witness Commitments + for (size_t i = 0; i < Flavor::NUM_WITNESS_ENTITIES; i++) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), proof_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), proof_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), proof_fields[offset + 3].witness_index); + offset += 4; + } + + // now the univariates + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N * Flavor::BATCHED_RELATION_PARTIAL_LENGTH; i++) { + builder.assert_equal(builder.add_variable(fr::random_element()), proof_fields[offset].witness_index); + offset++; + } + + // now the sumcheck evaluations + for (size_t i = 0; i < Flavor::NUM_ALL_ENTITIES; i++) { + builder.assert_equal(builder.add_variable(fr::random_element()), proof_fields[offset].witness_index); + offset++; + } + + // now the zeromorph commitments + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), proof_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), proof_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), proof_fields[offset + 3].witness_index); + offset += 4; + } + + // lastly the 2 commitments + for (size_t i = 0; i < 2; i++) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), proof_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), proof_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), proof_fields[offset + 3].witness_index); + offset += 4; + } + + ASSERT(offset == proof_size); +} + +} // namespace + +/** + * @brief Add constraints required to recursively verify an AVM proof + * + * @param builder + * @param input + * @param input_aggregation_object_indices. The aggregation object coming from previous Honk/Avm recursion constraints. + * @param has_valid_witness_assignment. Do we have witnesses or are we just generating keys? + */ +AggregationObjectIndices create_avm_recursion_constraints(Builder& builder, + const RecursionConstraint& input, + AggregationObjectIndices input_aggregation_object_indices, + bool has_valid_witness_assignments) +{ + using Flavor = AvmRecursiveFlavor_; + using RecursiveVerificationKey = Flavor::VerificationKey; + using RecursiveVerifier = AvmRecursiveVerifier_; + + ASSERT(input.proof_type == AVM); + + // Construct an in-circuit representation of the verification key. + std::vector key_fields; + key_fields.reserve(input.key.size()); + for (const auto& idx : input.key) { + auto field = field_ct::from_witness_index(&builder, idx); + key_fields.emplace_back(field); + } + + // TODO(JEANMON): Once we integrate with public inputs, we will have to decide whether we inject (see + // ProofSurgeon::create_indices_for_reconstructed_proof) them as part of proof_fields or through some separate + // argument like in the native verifier. The latter will be favored because the public inputs are not part of the + // transcript and the verifier code passes the proof to initialize the transcript. + // Create witness indices for the + // proof with public inputs reinserted std::vector proof_indices = + // ProofSurgeon::create_indices_for_reconstructed_proof(input.proof, input.public_inputs); + + std::vector proof_fields; + proof_fields.reserve(input.proof.size()); + + for (const auto& idx : input.proof) { + auto field = field_ct::from_witness_index(&builder, idx); + proof_fields.emplace_back(field); + } + + // Populate the key fields and proof fields with dummy values to prevent issues (e.g. points must be on curve). + if (!has_valid_witness_assignments) { + create_dummy_vkey_and_proof(builder, input.proof.size(), input.public_inputs.size(), key_fields, proof_fields); + } + + // Recursively verify the proof + auto vkey = std::make_shared(builder, key_fields); + RecursiveVerifier verifier(&builder, vkey); + aggregation_state_ct input_agg_obj = bb::stdlib::recursion::convert_witness_indices_to_agg_obj( + builder, input_aggregation_object_indices); + aggregation_state_ct output_agg_object = verifier.verify_proof(proof_fields, input_agg_obj); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/996): investigate whether assert_equal on public + // inputs is important, like what the plonk recursion constraint does. + + return output_agg_object.get_witness_indices(); +} + +} // namespace acir_format +#endif // DISABLE_AZTEC_VM diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.hpp new file mode 100644 index 00000000000..a68af42dcc8 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.hpp @@ -0,0 +1,17 @@ +#ifndef DISABLE_AZTEC_VM +#pragma once +#include "barretenberg/dsl/acir_format/recursion_constraint.hpp" +#include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" + +namespace acir_format { +using Builder = bb::UltraCircuitBuilder; + +using namespace bb; + +AggregationObjectIndices create_avm_recursion_constraints(Builder& builder, + const RecursionConstraint& input, + AggregationObjectIndices input_aggregation_object, + bool has_valid_witness_assignments); + +} // namespace acir_format +#endif // DISABLE_AZTEC_VM \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp new file mode 100644 index 00000000000..dbbd169c3cd --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp @@ -0,0 +1,139 @@ +#ifndef DISABLE_AZTEC_VM + +#include "avm_recursion_constraint.hpp" +#include "acir_format.hpp" +#include "acir_format_mocks.hpp" +#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp" +#include "barretenberg/ultra_honk/decider_keys.hpp" +#include "barretenberg/ultra_honk/ultra_prover.hpp" +#include "barretenberg/ultra_honk/ultra_verifier.hpp" +#include "barretenberg/vm/avm/generated/circuit_builder.hpp" +#include "barretenberg/vm/avm/generated/composer.hpp" +#include "barretenberg/vm/avm/generated/flavor.hpp" +#include "barretenberg/vm/avm/generated/prover.hpp" +#include "barretenberg/vm/avm/generated/verifier.hpp" +#include "barretenberg/vm/avm/tests/helpers.test.hpp" +#include "barretenberg/vm/avm/trace/trace.hpp" +#include "proof_surgeon.hpp" +#include +#include +#include + +using namespace acir_format; +using namespace bb; +using namespace bb::avm_trace; + +class AcirAvmRecursionConstraint : public ::testing::Test { + public: + using InnerBuilder = AvmCircuitBuilder; + using InnerProver = AvmProver; + using InnerVerifier = AvmVerifier; + + using OuterProver = UltraProver; + using OuterVerifier = UltraVerifier; + using OuterDeciderProvingKey = DeciderProvingKey_; + + using DeciderProvingKey = DeciderProvingKey_; + using OuterVerificationKey = UltraFlavor::VerificationKey; + using OuterBuilder = UltraCircuitBuilder; + + static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } + + static InnerBuilder create_inner_circuit() + { + VmPublicInputs public_inputs; + std::array kernel_inputs{}; + kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = 1000000; + kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = 1000000; + std::get<0>(public_inputs) = kernel_inputs; + + AvmTraceBuilder trace_builder(public_inputs); + InnerBuilder builder; + + trace_builder.op_set(0, 15, 1, AvmMemoryTag::U8); + trace_builder.op_set(0, 12, 2, AvmMemoryTag::U8); + trace_builder.op_add(0, 1, 2, 3, AvmMemoryTag::U8); + trace_builder.op_sub(0, 3, 2, 3, AvmMemoryTag::U8); + trace_builder.op_mul(0, 1, 1, 3, AvmMemoryTag::U8); + trace_builder.op_return(0, 0, 0); + auto trace = trace_builder.finalize(); // Passing true enables a longer trace with lookups + + builder.set_trace(std::move(trace)); + builder.check_circuit(); + return builder; + } + + /** + * @brief Create a circuit that recursively verifies one or more inner avm circuits + */ + static OuterBuilder create_outer_circuit(std::vector& inner_avm_circuits) + { + std::vector avm_recursion_constraints; + + SlabVector witness; + + for (auto& avm_circuit : inner_avm_circuits) { + AvmComposer composer = AvmComposer(); + InnerProver prover = composer.create_prover(avm_circuit); + InnerVerifier verifier = composer.create_verifier(avm_circuit); + + std::vector key_witnesses = verifier.key->to_field_elements(); + std::vector proof_witnesses = prover.construct_proof(); + + // Helper to append some values to the witness vector and return their corresponding indices + auto add_to_witness_and_track_indices = + [&witness](const std::vector& input) -> std::vector { + std::vector indices; + indices.reserve(input.size()); + auto witness_idx = static_cast(witness.size()); + for (const auto& value : input) { + witness.push_back(value); + indices.push_back(witness_idx++); + } + return indices; + }; + + RecursionConstraint avm_recursion_constraint{ + .key = add_to_witness_and_track_indices(key_witnesses), + .proof = add_to_witness_and_track_indices(proof_witnesses), + .public_inputs = {}, + .key_hash = 0, // not used + .proof_type = AVM, + }; + avm_recursion_constraints.push_back(avm_recursion_constraint); + } + + std::vector avm_recursion_opcode_indices(avm_recursion_constraints.size()); + std::iota(avm_recursion_opcode_indices.begin(), avm_recursion_opcode_indices.end(), 0); + + AcirFormat constraint_system; + constraint_system.varnum = static_cast(witness.size()); + constraint_system.recursive = false; + constraint_system.num_acir_opcodes = static_cast(avm_recursion_constraints.size()); + constraint_system.avm_recursion_constraints = avm_recursion_constraints; + constraint_system.original_opcode_indices = create_empty_original_opcode_indices(); + + mock_opcode_indices(constraint_system); + auto outer_circuit = create_circuit(constraint_system, /*size_hint*/ 0, witness); + return outer_circuit; + } +}; + +TEST_F(AcirAvmRecursionConstraint, TestBasicSingleAvmRecursionConstraint) +{ + std::vector layer_1_circuits; + layer_1_circuits.push_back(create_inner_circuit()); + auto layer_2_circuit = create_outer_circuit(layer_1_circuits); + + info("circuit gates = ", layer_2_circuit.get_num_gates()); + + auto proving_key = std::make_shared(layer_2_circuit); + OuterProver prover(proving_key); + info("prover gates = ", proving_key->proving_key.circuit_size); + auto proof = prover.construct_proof(); + auto verification_key = std::make_shared(proving_key->proving_key); + OuterVerifier verifier(verification_key); + EXPECT_EQ(verifier.verify_proof(proof), true); +} + +#endif // DISABLE_AZTEC_VM \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp index 2ecd7e37f61..a2dec9cce39 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/bigint_constraint.test.cpp @@ -194,6 +194,8 @@ TEST_F(BigIntTests, TestBigIntConstraintMultiple) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -268,6 +270,8 @@ TEST_F(BigIntTests, TestBigIntConstraintSimple) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = { from_le_bytes_constraint_bigint1 }, .bigint_to_le_bytes_constraints = { result2_to_le_bytes }, .bigint_operations = { add_constraint }, @@ -326,6 +330,8 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -389,6 +395,8 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse2) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -473,6 +481,8 @@ TEST_F(BigIntTests, TestBigIntDIV) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = { from_le_bytes_constraint_bigint1, from_le_bytes_constraint_bigint2 }, .bigint_to_le_bytes_constraints = { result3_to_le_bytes }, .bigint_operations = { div_constraint }, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp index aa2958d4d56..03ddf8035dc 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp @@ -162,6 +162,8 @@ TEST_F(UltraPlonkRAM, TestBlockConstraint) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -214,6 +216,8 @@ TEST_F(MegaHonk, Databus) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -321,6 +325,8 @@ TEST_F(MegaHonk, DatabusReturn) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp index 6f56c69851a..ac86757bb0d 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.test.cpp @@ -84,6 +84,8 @@ TEST_F(EcOperations, TestECOperations) .ec_add_constraints = { ec_add_constraint }, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -221,6 +223,8 @@ TEST_F(EcOperations, TestECMultiScalarMul) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp index 459aa7ccde5..d8bc40c5308 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp @@ -116,6 +116,8 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintSucceed) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -171,6 +173,8 @@ TEST_F(ECDSASecp256k1, TestECDSACompilesForVerifier) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -221,6 +225,8 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintFail) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp index ad09ed2cd8f..869c896ea6f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.test.cpp @@ -150,6 +150,8 @@ TEST(ECDSASecp256r1, test_hardcoded) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -207,6 +209,8 @@ TEST(ECDSASecp256r1, TestECDSAConstraintSucceed) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -262,6 +266,8 @@ TEST(ECDSASecp256r1, TestECDSACompilesForVerifier) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -313,6 +319,8 @@ TEST(ECDSASecp256r1, TestECDSAConstraintFail) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp index 8813b9c7614..28611d07622 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp @@ -16,6 +16,7 @@ using field_ct = stdlib::field_t; using bn254 = stdlib::bn254; using aggregation_state_ct = bb::stdlib::recursion::aggregation_state; +namespace { /** * @brief Creates a dummy vkey and proof object. * @details Populates the key and proof vectors with dummy values in the write_vk case when we don't have a valid @@ -110,7 +111,7 @@ void create_dummy_vkey_and_proof(Builder& builder, offset++; } - // now the sumcheck evalutions, which is just 43 0s + // now the sumcheck evaluations, which is just 43 0s for (size_t i = 0; i < Flavor::NUM_ALL_ENTITIES; i++) { builder.assert_equal(builder.add_variable(fr::random_element()), proof_fields[offset].witness_index); offset++; @@ -139,6 +140,7 @@ void create_dummy_vkey_and_proof(Builder& builder, } ASSERT(offset == proof_size + public_inputs_size); } +} // namespace /** * @brief Add constraints required to recursively verify an UltraHonk proof @@ -161,7 +163,7 @@ AggregationObjectIndices create_honk_recursion_constraints(Builder& builder, using RecursiveVerificationKey = Flavor::VerificationKey; using RecursiveVerifier = bb::stdlib::recursion::honk::UltraRecursiveVerifier_; - ASSERT(input.proof_type == HONK_RECURSION); + ASSERT(input.proof_type == HONK); // Construct an in-circuit representation of the verification key. // For now, the v-key is a circuit constant and is fixed for the circuit. diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp index a7209c74759..abf9be04f69 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp @@ -1,7 +1,7 @@ #include "honk_recursion_constraint.hpp" #include "acir_format.hpp" #include "acir_format_mocks.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" #include "proof_surgeon.hpp" @@ -112,6 +112,8 @@ class AcirHonkRecursionConstraint : public ::testing::Test { .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -164,47 +166,18 @@ class AcirHonkRecursionConstraint : public ::testing::Test { .proof = proof_indices, .public_inputs = inner_public_inputs, .key_hash = 0, // not used - .proof_type = HONK_RECURSION, + .proof_type = HONK, }; honk_recursion_constraints.push_back(honk_recursion_constraint); } - std::vector honk_recursion_opcode_indices(honk_recursion_constraints.size()); - std::iota(honk_recursion_opcode_indices.begin(), honk_recursion_opcode_indices.end(), 0); + AcirFormat constraint_system{}; + constraint_system.varnum = static_cast(witness.size()); + constraint_system.recursive = false; + constraint_system.num_acir_opcodes = static_cast(honk_recursion_constraints.size()); + constraint_system.honk_recursion_constraints = honk_recursion_constraints; + constraint_system.original_opcode_indices = create_empty_original_opcode_indices(); - AcirFormat constraint_system{ - .varnum = static_cast(witness.size()), - .recursive = false, - .num_acir_opcodes = static_cast(honk_recursion_constraints.size()), - .public_inputs = {}, - .logic_constraints = {}, - .range_constraints = {}, - .aes128_constraints = {}, - .sha256_constraints = {}, - .sha256_compression = {}, - .schnorr_constraints = {}, - .ecdsa_k1_constraints = {}, - .ecdsa_r1_constraints = {}, - .blake2s_constraints = {}, - .blake3_constraints = {}, - .keccak_constraints = {}, - .keccak_permutations = {}, - .pedersen_constraints = {}, - .pedersen_hash_constraints = {}, - .poseidon2_constraints = {}, - .multi_scalar_mul_constraints = {}, - .ec_add_constraints = {}, - .recursion_constraints = {}, - .honk_recursion_constraints = honk_recursion_constraints, - .bigint_from_le_bytes_constraints = {}, - .bigint_to_le_bytes_constraints = {}, - .bigint_operations = {}, - .assert_equalities = {}, - .poly_triple_constraints = {}, - .quad_constraints = {}, - .block_constraints = {}, - .original_opcode_indices = create_empty_original_opcode_indices(), - }; mock_opcode_indices(constraint_system); auto outer_circuit = create_circuit(constraint_system, /*size_hint*/ 0, witness, /*honk recursion*/ true); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp new file mode 100644 index 00000000000..bee50c74aa7 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp @@ -0,0 +1,278 @@ +#include "acir_format.hpp" +#include "acir_format_mocks.hpp" +#include "barretenberg/aztec_ivc/aztec_ivc.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" +#include "barretenberg/ultra_honk/ultra_prover.hpp" +#include "barretenberg/ultra_honk/ultra_verifier.hpp" +#include "honk_recursion_constraint.hpp" +#include "proof_surgeon.hpp" + +#include +#include + +using namespace acir_format; +using namespace bb; + +class IvcRecursionConstraintTest : public ::testing::Test { + + public: + using Builder = MegaCircuitBuilder; + using Flavor = MegaFlavor; + using FF = Flavor::FF; + using VerifierInputs = AztecIVC::VerifierInputs; + using QUEUE_TYPE = AztecIVC::QUEUE_TYPE; + using VerificationQueue = AztecIVC::VerificationQueue; + using ArithmeticConstraint = AcirFormat::PolyTripleConstraint; + + /** + * @brief Constuct a simple arbitrary circuit to represent a mock app circuit + * @details Includes a single unique public input for robustness and to distinguish the public inputs of one "app" + * from another in testing. + * + */ + static Builder construct_mock_app_circuit(AztecIVC& ivc) + { + Builder circuit{ ivc.goblin.op_queue }; + GoblinMockCircuits::construct_simple_circuit(circuit); + + // add a random (unique) public input + circuit.add_public_variable(FF::random_element()); + + return circuit; + } + + /** + * @brief Create an ACIR RecursionConstraint given the corresponding verifier inputs + * @brief In practice such constraints are created via a call to verify_proof(...) in noir + * + * @param input bberg style proof and verification key + * @param witness Array of witnesses into which the above data is placed + * @param num_public_inputs Number of public inputs to be extracted from the proof + * @return RecursionConstraint + */ + static RecursionConstraint create_recursion_constraint(const VerifierInputs& input, + SlabVector& witness, + const size_t num_public_inputs) + { + // Assemble simple vectors of witnesses for vkey and proof + std::vector key_witnesses = input.honk_verification_key->to_field_elements(); + std::vector proof_witnesses = input.proof; + + // Construct witness indices for each component in the constraint; populate the witness array + auto [key_indices, proof_indices, public_inputs_indices] = + ProofSurgeon::populate_recursion_witness_data(witness, proof_witnesses, key_witnesses, num_public_inputs); + + // The proof type can be either Oink or PG + PROOF_TYPE proof_type = input.type == QUEUE_TYPE::OINK ? OINK : PG; + + return RecursionConstraint{ + .key = key_indices, + .proof = proof_indices, + .public_inputs = public_inputs_indices, + .key_hash = 0, // not used + .proof_type = proof_type, + }; + } + + /** + * @brief Create an arithmetic constraint fixing the first public input witness to it's present value + * @details Meant to mimic the "business logic" of the aztec kernel. Used to facilitate failure testing since this + * will lead to failure of the kernel circuit to verify if a different proof witness is used in the business logic + * VS the recursive verification logic. + * + * @param public_inputs Witness indices of public inputs of some proof to be constrained + * @param witness + * @return ArithmeticConstraint + */ + static ArithmeticConstraint create_public_input_value_constraint(const std::vector& public_inputs, + const SlabVector& witness) + { + const uint32_t pub_input_idx = public_inputs[0]; + const FF pub_input_val = witness[pub_input_idx]; + return { + .a = pub_input_idx, + .b = 0, + .c = 0, + .q_m = 0, + .q_l = -1, + .q_r = 0, + .q_o = 0, + .q_c = pub_input_val, + }; + } + + /** + * @brief Generate an acir program {constraints, witness} for a mock kernel + * @details The IVC contains and internal verification queue that contains proofs to be recursively verified. + * Construct an AcirProgram with a RecursionConstraint for each entry in the ivc verification queue. (In practice + * these constraints would come directly from calls to verify_proof in noir). Also add mock "business logic" which + * simply enforces some constraint on the public inputs of the proof. + * @note This method needs the number of public inputs in each proof-to-be-verified so they can be extracted and + * provided separately as is required in the acir constraint system. + * + * @param ivc + * @param inner_circuit_num_pub_inputs Num pub inputs for each circuit whose accumulation is recursively verified + * @return Builder + */ + static AcirProgram construct_mock_kernel_program(const VerificationQueue& verification_queue, + const std::vector& inner_circuit_num_pub_inputs) + { + ASSERT(verification_queue.size() == inner_circuit_num_pub_inputs.size()); + + AcirProgram program; + + // Construct recursion constraints based on the ivc verification queue; populate the witness along the way + std::vector ivc_recursion_constraints; + ivc_recursion_constraints.reserve(verification_queue.size()); + for (size_t idx = 0; idx < verification_queue.size(); ++idx) { + ivc_recursion_constraints.push_back(create_recursion_constraint( + verification_queue[idx], program.witness, inner_circuit_num_pub_inputs[idx])); + } + + // Add some mock kernel "business logic" which simply fixes one of the public inputs to a particular value + ArithmeticConstraint pub_input_constraint = + create_public_input_value_constraint(ivc_recursion_constraints[0].public_inputs, program.witness); + + // Construct a constraint system containing the business logic and ivc recursion constraints + program.constraints.varnum = static_cast(program.witness.size()); + program.constraints.recursive = false; + program.constraints.num_acir_opcodes = static_cast(ivc_recursion_constraints.size()); + program.constraints.poly_triple_constraints = { pub_input_constraint }; + program.constraints.ivc_recursion_constraints = ivc_recursion_constraints; + program.constraints.original_opcode_indices = create_empty_original_opcode_indices(); + mock_opcode_indices(program.constraints); + + return program; + } + + protected: + void SetUp() override + { + bb::srs::init_crs_factory("../srs_db/ignition"); + srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } +}; + +/** + * @brief Test IVC accumulation of a one app and one kernel; The kernel includes a recursive oink verification for the + * app, specified via an ACIR RecursionConstraint. + */ +TEST_F(IvcRecursionConstraintTest, AccumulateTwo) +{ + AztecIVC ivc; + ivc.trace_structure = TraceStructure::SMALL_TEST; + + // construct a mock app_circuit + Builder app_circuit = construct_mock_app_circuit(ivc); + + // Complete instance and generate an oink proof + ivc.accumulate(app_circuit); + + // Construct kernel_0 consisting only of the kernel completion logic + AcirProgram program_0 = construct_mock_kernel_program(ivc.verification_queue, { app_circuit.public_inputs.size() }); + Builder kernel_0 = acir_format::create_kernel_circuit(program_0.constraints, ivc, program_0.witness); + + EXPECT_TRUE(CircuitChecker::check(kernel_0)); + ivc.accumulate(kernel_0); + + EXPECT_TRUE(ivc.prove_and_verify()); +} + +/** + * @brief Test IVC accumulation of two apps and two kernels; The first kernel contains a recursive oink verification and + * the second contains two recursive PG verifications, all specified via ACIR RecursionConstraints. + */ +TEST_F(IvcRecursionConstraintTest, AccumulateFour) +{ + AztecIVC ivc; + ivc.trace_structure = TraceStructure::SMALL_TEST; + + // construct a mock app_circuit + Builder app_circuit_0 = construct_mock_app_circuit(ivc); + ivc.accumulate(app_circuit_0); + + // Construct kernel_0; consists of a single oink recursive verification for app (plus databus/merge logic) + size_t num_pub_inputs_app_0 = app_circuit_0.public_inputs.size(); + AcirProgram program_0 = construct_mock_kernel_program(ivc.verification_queue, { num_pub_inputs_app_0 }); + Builder kernel_0 = acir_format::create_kernel_circuit(program_0.constraints, ivc, program_0.witness); + ivc.accumulate(kernel_0); + + // construct a mock app_circuit + Builder app_circuit_1 = construct_mock_app_circuit(ivc); + ivc.accumulate(app_circuit_1); + + // Construct kernel_1; consists of two PG recursive verifications for kernel_0 and app_1 (plus databus/merge logic) + size_t num_pub_inputs_kernel_0 = kernel_0.public_inputs.size(); + size_t num_pub_inputs_app_1 = app_circuit_0.public_inputs.size(); + AcirProgram program_1 = + construct_mock_kernel_program(ivc.verification_queue, { num_pub_inputs_kernel_0, num_pub_inputs_app_1 }); + Builder kernel_1 = acir_format::create_kernel_circuit(program_1.constraints, ivc, program_1.witness); + + EXPECT_TRUE(CircuitChecker::check(kernel_1)); + ivc.accumulate(kernel_1); + + EXPECT_TRUE(ivc.prove_and_verify()); +} + +/** + * @brief Demonstrate failure of the IVC if the proof witness differs between those encoded in the constraint system + * (i.e. those used in the noir program) and those used in constructing the recursive verifiers internally + * @brief The idea is to construct two valid but unique verification queue entries of the form {proof, vkey}. One is + * used to construct the acir constraint system and the other is used to construct the recursive verification logic + * internally in the IVC. Since the proof/vkey witnesses in the constraint system are asserted equal to those used to + * construct the recursive verifiers, the use of different verification queue witnesses should result in failure as long + * as they were used in some nontrivial way in the main logic of the kernel. (Specifically, failure results from a + * failure of the "business logic" of the kernel which constrains one of the public inputs to a particular value). + */ +TEST_F(IvcRecursionConstraintTest, AccumulateTwoFailure) +{ + // Accumulate a single app in order to construct a valid verification queue entry {proof, vkey} to be used later on. + // Demonstrate that it is indeed valid by completing the IVC with a kernel (which recursively verifies the entry) + // then proving and verifying the full IVC. + VerifierInputs alternative_verification_queue_entry; + { + AztecIVC ivc; + ivc.trace_structure = TraceStructure::SMALL_TEST; + + // construct and accumulate a mock app circuit with a single unique public input + Builder app_circuit = construct_mock_app_circuit(ivc); + ivc.accumulate(app_circuit); + + // Save the single entry in the verification queue at this point + alternative_verification_queue_entry = ivc.verification_queue[0]; + + // Construct and accumulate kernel_0 + size_t num_pub_inputs_app = app_circuit.public_inputs.size(); + AcirProgram program_0 = construct_mock_kernel_program(ivc.verification_queue, { num_pub_inputs_app }); + Builder kernel_0 = acir_format::create_kernel_circuit(program_0.constraints, ivc, program_0.witness); + ivc.accumulate(kernel_0); + + EXPECT_TRUE(ivc.prove_and_verify()); + } + + // Repeat a similar IVC but use the alternative queue entry just created to provide different (but independently + // valid) witnesses during constraint system construction VS recursive verifier construction. + + AztecIVC ivc; + ivc.trace_structure = TraceStructure::SMALL_TEST; + + // construct and accumulate a mock app circuit with a single unique public input + Builder app_circuit = construct_mock_app_circuit(ivc); + ivc.accumulate(app_circuit); + + // Construct kernel_0 + AcirProgram program_0 = construct_mock_kernel_program(ivc.verification_queue, { app_circuit.public_inputs.size() }); + + // Replace the existing verification queue entry that was used to construct the acir constraint system for the + // kernel with a different (but valid, as shown above) set of inputs + ivc.verification_queue[0] = alternative_verification_queue_entry; + Builder kernel_0 = acir_format::create_kernel_circuit(program_0.constraints, ivc, program_0.witness); + + // The witness should fail to check due to the business logic of the kernel failing + EXPECT_FALSE(CircuitChecker::check(kernel_0)); + ivc.accumulate(kernel_0); + + // The full IVC should of course also fail to verify since we've accumulated an invalid witness for the kernel + EXPECT_FALSE(ivc.prove_and_verify()); +} diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.test.cpp index 57db2db8c71..47bd777cfce 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.test.cpp @@ -84,6 +84,8 @@ TEST_F(MSMTests, TestMSM) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.test.cpp index 150acbc0561..c3dc81fd9bc 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.test.cpp @@ -64,6 +64,8 @@ TEST_F(Poseidon2Tests, TestPoseidon2Permutation) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp index c4eaaefad1b..ef342ff45c2 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp @@ -28,7 +28,7 @@ class ProofSurgeon { std::vector proof; proof.reserve(proof_in.size() + public_inputs.size()); - // Construct a the complete proof as the concatenation {"initial data" | public_inputs | proof_in} + // Construct the complete proof as the concatenation {"initial data" | public_inputs | proof_in} proof.insert(proof.end(), proof_in.begin(), proof_in.begin() + HONK_RECURSION_PUBLIC_INPUT_OFFSET); proof.insert(proof.end(), public_inputs.begin(), public_inputs.end()); proof.insert(proof.end(), proof_in.begin() + HONK_RECURSION_PUBLIC_INPUT_OFFSET, proof_in.end()); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp index 1a98fd15ff6..e53937bc8be 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp @@ -8,7 +8,7 @@ namespace acir_format { // Used to specify the type of recursive verifier via the proof_type specified by the RecursiveAggregation opcode from // ACIR -enum PROOF_TYPE { PLONK_RECURSION, HONK_RECURSION }; +enum PROOF_TYPE { PLONK, HONK, OINK, PG, AVM }; using namespace bb::plonk; using Builder = bb::UltraCircuitBuilder; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp index c01d6edfc23..1811b8d7fee 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp @@ -109,6 +109,8 @@ Builder create_inner_circuit() .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, @@ -210,7 +212,7 @@ Builder create_outer_circuit(std::vector& inner_circuits) .proof = proof_indices, .public_inputs = inner_public_inputs, .key_hash = key_hash_start_idx, - .proof_type = PLONK_RECURSION, + .proof_type = PLONK, }; recursion_constraints.push_back(recursion_constraint); @@ -271,6 +273,8 @@ Builder create_outer_circuit(std::vector& inner_circuits) .ec_add_constraints = {}, .recursion_constraints = recursion_constraints, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp index e92950be4e7..a9975e3f57b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -632,8 +632,8 @@ struct BrilligOpcode { struct CalldataCopy { Program::MemoryAddress destination_address; - uint64_t size; - uint64_t offset; + Program::MemoryAddress size_address; + Program::MemoryAddress offset_address; friend bool operator==(const CalldataCopy&, const CalldataCopy&); std::vector bincodeSerialize() const; @@ -6320,10 +6320,10 @@ inline bool operator==(const BrilligOpcode::CalldataCopy& lhs, const BrilligOpco if (!(lhs.destination_address == rhs.destination_address)) { return false; } - if (!(lhs.size == rhs.size)) { + if (!(lhs.size_address == rhs.size_address)) { return false; } - if (!(lhs.offset == rhs.offset)) { + if (!(lhs.offset_address == rhs.offset_address)) { return false; } return true; @@ -6354,8 +6354,8 @@ void serde::Serializable::serialize( const Program::BrilligOpcode::CalldataCopy& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination_address, serializer); - serde::Serializable::serialize(obj.size, serializer); - serde::Serializable::serialize(obj.offset, serializer); + serde::Serializable::serialize(obj.size_address, serializer); + serde::Serializable::serialize(obj.offset_address, serializer); } template <> @@ -6365,8 +6365,8 @@ Program::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize(deserializer); - obj.size = serde::Deserializable::deserialize(deserializer); - obj.offset = serde::Deserializable::deserialize(deserializer); + obj.size_address = serde::Deserializable::deserialize(deserializer); + obj.offset_address = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp index 0f87cb34f94..3f27b41c584 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.test.cpp @@ -59,6 +59,8 @@ TEST_F(Sha256Tests, TestSha256Compression) .ec_add_constraints = {}, .recursion_constraints = {}, .honk_recursion_constraints = {}, + .avm_recursion_constraints = {}, + .ivc_recursion_constraints = {}, .bigint_from_le_bytes_constraints = {}, .bigint_to_le_bytes_constraints = {}, .bigint_operations = {}, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp index 711ed414a81..3a62a688bac 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp @@ -17,6 +17,8 @@ using { equal as == } for Fr global; uint256 constant MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order +Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1); + // Instantiation library FrLib { @@ -43,14 +45,14 @@ library FrLib // Call the modexp precompile to invert in the field assembly { - let free := mload(0x40) - mstore(free, 0x20) - mstore(add(free, 0x20), 0x20) + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) mstore(add(free, 0x40), 0x20) mstore(add(free, 0x60), v) - mstore(add(free, 0x80), sub(MODULUS, 2)) + mstore(add(free, 0x80), sub(MODULUS, 2)) mstore(add(free, 0xa0), MODULUS) - let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) if iszero(success) { revert(0, 0) } @@ -68,17 +70,17 @@ library FrLib // Call the modexp precompile to invert in the field assembly { - let free := mload(0x40) - mstore(free, 0x20) - mstore(add(free, 0x20), 0x20) + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) mstore(add(free, 0x40), 0x20) mstore(add(free, 0x60), b) - mstore(add(free, 0x80), v) - mstore(add(free, 0xa0), MODULUS) - let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) - if iszero(success) { - revert(0, 0) - } + mstore(add(free, 0x80), v) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } result := mload(0x00) } @@ -87,7 +89,6 @@ library FrLib function div(Fr numerator, Fr denominator) internal view returns(Fr) { - Fr inversion = invert(denominator); return numerator * invert(denominator); } } @@ -131,14 +132,18 @@ function equal(Fr a, Fr b) pure returns(bool) uint256 constant CONST_PROOF_SIZE_LOG_N = 28; -uint256 constant NUMBER_OF_SUBRELATIONS = 18; -uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 7; -uint256 constant NUMBER_OF_ENTITIES = 42; -uint256 constant NUMBER_OF_ALPHAS = 17; +uint256 constant NUMBER_OF_SUBRELATIONS = 26; +uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8; +uint256 constant NUMBER_OF_ENTITIES = 44; +uint256 constant NUMBER_UNSHIFTED = 35; +uint256 constant NUMBER_TO_BE_SHIFTED = 9; + +// Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1 +uint256 constant NUMBER_OF_ALPHAS = 25; // Prime field order -uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order -uint256 constant P = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order +uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q +uint256 constant P = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order, F_r // ENUM FOR WIRES enum WIRE { @@ -153,6 +158,8 @@ enum WIRE { Q_ELLIPTIC, Q_AUX, Q_LOOKUP, + Q_POSEIDON2_EXTERNAL, + Q_POSEIDON2_INTERNAL, SIGMA_1, SIGMA_2, SIGMA_3, @@ -216,6 +223,8 @@ library Honk { G1Point qAux; // Auxillary G1Point qElliptic; // Auxillary G1Point qLookup; // Lookup + G1Point qPoseidon2External; + G1Point qPoseidon2Internal; // Copy cnstraints G1Point s1; G1Point s2; @@ -283,34 +292,45 @@ struct Transcript { Fr lookupGrandProductDelta; } -library TranscriptLib -{ - function generateTranscript(Honk.Proof memory proof, - Honk.VerificationKey memory vk, - bytes32[] calldata publicInputs) internal view returns(Transcript memory t) +library TranscriptLib { + function generateTranscript(Honk.Proof memory proof, bytes32[] calldata publicInputs, uint256 publicInputsSize) + internal + view + returns (Transcript memory t) { - (t.eta, t.etaTwo, t.etaThree) = generateEtaChallenge(proof, publicInputs); + Fr previousChallenge; + (t.eta, t.etaTwo, t.etaThree, previousChallenge) = generateEtaChallenge(proof, publicInputs, publicInputsSize); - (t.beta, t.gamma) = generateBetaAndGammaChallenges(t.etaThree, proof); + (t.beta, t.gamma, previousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); - t.alphas = generateAlphaChallenges(t.gamma, proof); + (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); - t.gateChallenges = generateGateChallenges(t.alphas[NUMBER_OF_ALPHAS - 1]); + (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge); - t.sumCheckUChallenges = generateSumcheckChallenges(proof, t.gateChallenges[CONST_PROOF_SIZE_LOG_N - 1]); - t.rho = generateRhoChallenge(proof, t.sumCheckUChallenges[CONST_PROOF_SIZE_LOG_N - 1]); + (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge); + (t.rho, previousChallenge) = generateRhoChallenge(proof, previousChallenge); - t.zmY = generateZMYChallenge(t.rho, proof); + (t.zmY, previousChallenge) = generateZMYChallenge(previousChallenge, proof); - (t.zmX, t.zmZ) = generateZMXZChallenges(t.zmY, proof); + (t.zmX, t.zmZ, previousChallenge) = generateZMXZChallenges(previousChallenge, proof); return t; } - function generateEtaChallenge(Honk.Proof memory proof, bytes32[] calldata publicInputs) - internal view returns(Fr eta, Fr etaTwo, Fr etaThree) + function splitChallenge(Fr challenge) internal pure returns (Fr first, Fr second) { + uint256 challengeU256 = uint256(Fr.unwrap(challenge)); + uint256 lo = challengeU256 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + uint256 hi = challengeU256 >> 128; + first = FrLib.fromBytes32(bytes32(lo)); + second = FrLib.fromBytes32(bytes32(hi)); + } + + function generateEtaChallenge(Honk.Proof memory proof, bytes32[] calldata publicInputs, uint256 publicInputsSize) + internal + view + returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { - bytes32[3 + NUMBER_OF_PUBLIC_INPUTS + 12] memory round0; + bytes32[] memory round0 = new bytes32[](3 + NUMBER_OF_PUBLIC_INPUTS + 12); round0[0] = bytes32(proof.circuitSize); round0[1] = bytes32(proof.publicInputsSize); round0[2] = bytes32(proof.publicInputsOffset); @@ -333,13 +353,14 @@ library TranscriptLib round0[3 + NUMBER_OF_PUBLIC_INPUTS + 10] = bytes32(proof.w3.y_0); round0[3 + NUMBER_OF_PUBLIC_INPUTS + 11] = bytes32(proof.w3.y_1); - eta = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); - etaTwo = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(eta)))); - etaThree = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(etaTwo)))); + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); + (eta, etaTwo) = splitChallenge(previousChallenge); + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + Fr unused; + (etaThree, unused) = splitChallenge(previousChallenge); } - function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal view returns(Fr beta, Fr gamma) + function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.Proof memory proof) internal view returns (Fr beta, Fr gamma, Fr nextPreviousChallenge) { bytes32[13] memory round1; round1[0] = FrLib.toBytes32(previousChallenge); @@ -356,13 +377,12 @@ library TranscriptLib round1[11] = bytes32(proof.w4.y_0); round1[12] = bytes32(proof.w4.y_1); - beta = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); - gamma = FrLib.fromBytes32(keccak256(abi.encodePacked(beta))); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); + (beta, gamma) = splitChallenge(nextPreviousChallenge); } // Alpha challenges non-linearise the gate contributions - function generateAlphaChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal view returns(Fr[NUMBER_OF_ALPHAS] memory alphas) + function generateAlphaChallenges(Fr previousChallenge, Honk.Proof memory proof) internal view returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge) { // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup uint256[9] memory alpha0; @@ -376,52 +396,63 @@ library TranscriptLib alpha0[7] = proof.zPerm.y_0; alpha0[8] = proof.zPerm.y_1; - alphas[0] = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + (alphas[0], alphas[1]) = splitChallenge(nextPreviousChallenge); - Fr prevChallenge = alphas[0]; - for (uint256 i = 1; i < NUMBER_OF_ALPHAS; i++) { - prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(prevChallenge)))); - alphas[i] = prevChallenge; + for (uint256 i = 1; i < NUMBER_OF_ALPHAS / 2; i++) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + (alphas[2 * i], alphas[2 * i + 1]) = splitChallenge(nextPreviousChallenge); + } + if (((NUMBER_OF_ALPHAS & 1) == 1) && (NUMBER_OF_ALPHAS > 2)) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + Fr unused; + (alphas[NUMBER_OF_ALPHAS - 1], unused) = splitChallenge(nextPreviousChallenge); } } - function generateGateChallenges(Fr previousChallenge) internal view returns(Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges) + function generateGateChallenges(Fr previousChallenge) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge) { for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); - gateChallenges[i] = previousChallenge; + Fr unused; + (gateChallenges[i], unused) = splitChallenge(previousChallenge); } + nextPreviousChallenge = previousChallenge; } - function generateSumcheckChallenges(Honk.Proof memory proof, Fr prevChallenge) - internal view returns(Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges) + function generateSumcheckChallenges(Honk.Proof memory proof, Fr prevChallenge) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges, Fr nextPreviousChallenge) { for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { Fr[BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; univariateChal[0] = prevChallenge; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1098): memcpy for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; } - - sumcheckChallenges[i] = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); - prevChallenge = sumcheckChallenges[i]; + prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); + Fr unused; + (sumcheckChallenges[i], unused) = splitChallenge(prevChallenge); } + nextPreviousChallenge = prevChallenge; } - function generateRhoChallenge(Honk.Proof memory proof, Fr prevChallenge) internal view returns(Fr rho) + function generateRhoChallenge(Honk.Proof memory proof, Fr prevChallenge) internal view returns (Fr rho, Fr nextPreviousChallenge) { Fr[NUMBER_OF_ENTITIES + 1] memory rhoChallengeElements; rhoChallengeElements[0] = prevChallenge; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1098): memcpy for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { rhoChallengeElements[i + 1] = proof.sumcheckEvaluations[i]; } - rho = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + Fr unused; + (rho, unused) = splitChallenge(nextPreviousChallenge); } - function generateZMYChallenge(Fr previousChallenge, Honk.Proof memory proof) internal view returns(Fr zeromorphY) + function generateZMYChallenge(Fr previousChallenge, Honk.Proof memory proof) internal view returns (Fr zeromorphY, Fr nextPreviousChallenge) { uint256[CONST_PROOF_SIZE_LOG_N * 4 + 1] memory zmY; zmY[0] = Fr.unwrap(previousChallenge); @@ -433,11 +464,12 @@ library TranscriptLib zmY[4 + i * 4] = proof.zmCqs[i].y_1; } - zeromorphY = FrLib.fromBytes32(keccak256(abi.encodePacked(zmY))); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(zmY))); + Fr unused; + (zeromorphY, unused) = splitChallenge(nextPreviousChallenge); } - function generateZMXZChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal view returns(Fr zeromorphX, Fr zeromorphZ) + function generateZMXZChallenges(Fr previousChallenge, Honk.Proof memory proof) internal pure returns (Fr zeromorphX, Fr zeromorphZ, Fr nextPreviousChallenge) { uint256[4 + 1] memory buf; buf[0] = Fr.unwrap(previousChallenge); @@ -447,8 +479,8 @@ library TranscriptLib buf[3] = proof.zmCq.y_0; buf[4] = proof.zmCq.y_1; - zeromorphX = FrLib.fromBytes32(keccak256(abi.encodePacked(buf))); - zeromorphZ = FrLib.fromBytes32(keccak256(abi.encodePacked(zeromorphX))); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(buf))); + (zeromorphX, zeromorphZ) = splitChallenge(nextPreviousChallenge); } } @@ -491,316 +523,28 @@ function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point mem return point; } -// Errors -error PublicInputsLengthWrong(); -error SumcheckFailed(); -error ZeromorphFailed(); -interface IVerifier { - function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool); -} - -/// Smart contract verifier of honk proofs -contract HonkVerifier is IVerifier -{ +library RelationsLib { Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) - function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns(bool) - { - Honk.VerificationKey memory vk = loadVerificationKey(); - Honk.Proof memory p = loadProof(proof); - - if (publicInputs.length != vk.publicInputsSize) { - revert PublicInputsLengthWrong(); - } - - // Generate the fiat shamir challenges for the whole protocol - Transcript memory t = TranscriptLib.generateTranscript(p, vk, publicInputs); - - // Compute the public input delta - t.publicInputsDelta = - computePublicInputDelta(publicInputs, t.beta, t.gamma, vk.circuitSize, p.publicInputsOffset); - - // Sumcheck - bool sumcheckVerified = verifySumcheck(p, t); - if (!sumcheckVerified) - revert SumcheckFailed(); - - // Zeromorph - bool zeromorphVerified = verifyZeroMorph(p, vk, t); - if (!zeromorphVerified) - revert ZeromorphFailed(); - - return sumcheckVerified && zeromorphVerified; // Boolean condition not required - nice for vanity :) - } - - function loadVerificationKey() internal view returns(Honk.VerificationKey memory) - { - return HonkVerificationKey.loadVerificationKey(); - } - - function loadProof(bytes calldata proof) internal view returns(Honk.Proof memory) - { - Honk.Proof memory p; - - // Metadata - p.circuitSize = uint256(bytes32(proof [0x00:0x20])); - p.publicInputsSize = uint256(bytes32(proof [0x20:0x40])); - p.publicInputsOffset = uint256(bytes32(proof [0x40:0x60])); - - // Commitments - p.w1 = Honk.G1ProofPoint({ - x_0 : uint256(bytes32(proof [0x60:0x80])), - x_1 : uint256(bytes32(proof [0x80:0xa0])), - y_0 : uint256(bytes32(proof [0xa0:0xc0])), - y_1 : uint256(bytes32(proof [0xc0:0xe0])) - }); - - p.w2 = Honk.G1ProofPoint({ - x_0 : uint256(bytes32(proof [0xe0:0x100])), - x_1 : uint256(bytes32(proof [0x100:0x120])), - y_0 : uint256(bytes32(proof [0x120:0x140])), - y_1 : uint256(bytes32(proof [0x140:0x160])) - }); - p.w3 = Honk.G1ProofPoint({ - x_0 : uint256(bytes32(proof [0x160:0x180])), - x_1 : uint256(bytes32(proof [0x180:0x1a0])), - y_0 : uint256(bytes32(proof [0x1a0:0x1c0])), - y_1 : uint256(bytes32(proof [0x1c0:0x1e0])) - }); - - // Lookup / Permutation Helper Commitments - p.lookupReadCounts = Honk.G1ProofPoint({ - x_0 : uint256(bytes32(proof [0x1e0:0x200])), - x_1 : uint256(bytes32(proof [0x200:0x220])), - y_0 : uint256(bytes32(proof [0x220:0x240])), - y_1 : uint256(bytes32(proof [0x240:0x260])) - }); - p.lookupReadTags = Honk.G1ProofPoint({ - x_0 : uint256(bytes32(proof [0x260:0x280])), - x_1 : uint256(bytes32(proof [0x280:0x2a0])), - y_0 : uint256(bytes32(proof [0x2a0:0x2c0])), - y_1 : uint256(bytes32(proof [0x2c0:0x2e0])) - }); - p.w4 = Honk.G1ProofPoint({ - x_0 : uint256(bytes32(proof [0x2e0:0x300])), - x_1 : uint256(bytes32(proof [0x300:0x320])), - y_0 : uint256(bytes32(proof [0x320:0x340])), - y_1 : uint256(bytes32(proof [0x340:0x360])) - }); - p.lookupInverses = Honk.G1ProofPoint({ - x_0 : uint256(bytes32(proof [0x360:0x380])), - x_1 : uint256(bytes32(proof [0x380:0x3a0])), - y_0 : uint256(bytes32(proof [0x3a0:0x3c0])), - y_1 : uint256(bytes32(proof [0x3c0:0x3e0])) - }); - p.zPerm = Honk.G1ProofPoint({ - x_0 : uint256(bytes32(proof [0x3e0:0x400])), - x_1 : uint256(bytes32(proof [0x400:0x420])), - y_0 : uint256(bytes32(proof [0x420:0x440])), - y_1 : uint256(bytes32(proof [0x440:0x460])) - }); - - // TEMP the boundary of what has already been read - uint256 boundary = 0x460; - - // Sumcheck univariates - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - // The loop boundary of i, this will shift forward on each evaluation - uint256 loop_boundary = boundary + (i * 0x20 * BATCHED_RELATION_PARTIAL_LENGTH); - - for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { - uint256 start = loop_boundary + (j * 0x20); - uint256 end = start + 0x20; - p.sumcheckUnivariates[i][j] = FrLib.fromBytes32(bytes32(proof [start:end])); - } - } - - boundary = boundary + (CONST_PROOF_SIZE_LOG_N * BATCHED_RELATION_PARTIAL_LENGTH * 0x20); - // Sumcheck evaluations - for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { - uint256 start = boundary + (i * 0x20); - uint256 end = start + 0x20; - p.sumcheckEvaluations[i] = FrLib.fromBytes32(bytes32(proof [start:end])); - } - - boundary = boundary + (NUMBER_OF_ENTITIES * 0x20); - // Zero morph Commitments - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - // Explicitly stating the x0, x1, y0, y1 start and end boundaries to make the calldata slicing bearable - uint256 xStart = boundary + (i * 0x80); - uint256 xEnd = xStart + 0x20; - - uint256 x1Start = xEnd; - uint256 x1End = x1Start + 0x20; - - uint256 yStart = x1End; - uint256 yEnd = yStart + 0x20; - - uint256 y1Start = yEnd; - uint256 y1End = y1Start + 0x20; - - p.zmCqs[i] = Honk.G1ProofPoint({ - x_0 : uint256(bytes32(proof [xStart:xEnd])), - x_1 : uint256(bytes32(proof [x1Start:x1End])), - y_0 : uint256(bytes32(proof [yStart:yEnd])), - y_1 : uint256(bytes32(proof [y1Start:y1End])) - }); - } - - boundary = boundary + (CONST_PROOF_SIZE_LOG_N * 0x80); - - p.zmCq = Honk.G1ProofPoint({ - x_0 : uint256(bytes32(proof [boundary:boundary + 0x20])), - x_1 : uint256(bytes32(proof [boundary + 0x20:boundary + 0x40])), - y_0 : uint256(bytes32(proof [boundary + 0x40:boundary + 0x60])), - y_1 : uint256(bytes32(proof [boundary + 0x60:boundary + 0x80])) - }); - - p.zmPi = Honk.G1ProofPoint({ - x_0 : uint256(bytes32(proof [boundary + 0x80:boundary + 0xa0])), - x_1 : uint256(bytes32(proof [boundary + 0xa0:boundary + 0xc0])), - y_0 : uint256(bytes32(proof [boundary + 0xc0:boundary + 0xe0])), - y_1 : uint256(bytes32(proof [boundary + 0xe0:boundary + 0x100])) - }); - - return p; - } - - function computePublicInputDelta( - bytes32[] memory publicInputs, Fr beta, Fr gamma, uint256 domainSize, uint256 offset) - internal view returns(Fr publicInputDelta) - { - Fr numerator = Fr.wrap(1); - Fr denominator = Fr.wrap(1); - - Fr numeratorAcc = gamma + (beta * FrLib.from(domainSize + offset)); - Fr denominatorAcc = gamma - (beta * FrLib.from(offset + 1)); - - { - for (uint256 i = 0; i < NUMBER_OF_PUBLIC_INPUTS; i++) { - Fr pubInput = FrLib.fromBytes32(publicInputs[i]); - - numerator = numerator * (numeratorAcc + pubInput); - denominator = denominator * (denominatorAcc + pubInput); - - numeratorAcc = numeratorAcc + beta; - denominatorAcc = denominatorAcc - beta; - } - } - - // Fr delta = numerator / denominator; // TOOO: batch invert later? - publicInputDelta = FrLib.div(numerator, denominator); - } - - uint256 constant ROUND_TARGET = 0; - - function verifySumcheck(Honk.Proof memory proof, Transcript memory tp) internal view returns(bool verified) - { - Fr roundTarget; - Fr powPartialEvaluation = Fr.wrap(1); - - // We perform sumcheck reductions over log n rounds ( the multivariate degree ) - for (uint256 round; round < LOG_N; ++round) { - Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round]; - bool valid = checkSum(roundUnivariate, roundTarget); - if (!valid) - revert SumcheckFailed(); - - Fr roundChallenge = tp.sumCheckUChallenges[round]; - - // Update the round target for the next rounf - roundTarget = computeNextTargetSum(roundUnivariate, roundChallenge); - powPartialEvaluation = partiallyEvaluatePOW(tp, powPartialEvaluation, roundChallenge, round); - } - - // Last round - Fr grandHonkRelationSum = accumulateRelationEvaluations(proof, tp, powPartialEvaluation); - verified = (grandHonkRelationSum == roundTarget); - } - - function checkSum(Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate, Fr roundTarget) - internal view returns(bool checked) - { - Fr totalSum = roundUnivariate[0] + roundUnivariate[1]; - checked = totalSum == roundTarget; - } - - // Return the new target sum for the next sumcheck round - function computeNextTargetSum(Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge) - internal view returns(Fr targetSum) - { - Fr[7] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ - Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000002d0), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff89), - Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000030), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffdd), - Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000030), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff89), - Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000002d0) - ]; - - Fr[7] memory BARYCENTRIC_DOMAIN = - [ Fr.wrap(0x00), Fr.wrap(0x01), Fr.wrap(0x02), Fr.wrap(0x03), Fr.wrap(0x04), Fr.wrap(0x05), Fr.wrap(0x06) ]; - // To compute the next target sum, we evaluate the given univariate at a point u (challenge). - - // Performing Barycentric evaluations - // Compute B(x) - Fr numeratorValue = Fr.wrap(1); - for (uint256 i; i < BATCHED_RELATION_PARTIAL_LENGTH; ++i) { - numeratorValue = numeratorValue * (roundChallenge - Fr.wrap(i)); - } - - // Calculate domain size N of inverses - Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory denominatorInverses; - for (uint256 i; i < BATCHED_RELATION_PARTIAL_LENGTH; ++i) { - Fr inv = BARYCENTRIC_LAGRANGE_DENOMINATORS[i]; - inv = inv * (roundChallenge - BARYCENTRIC_DOMAIN[i]); - inv = FrLib.invert(inv); - denominatorInverses[i] = inv; - } - - for (uint256 i; i < BATCHED_RELATION_PARTIAL_LENGTH; ++i) { - Fr term = roundUnivariates[i]; - term = term * denominatorInverses[i]; - targetSum = targetSum + term; - } - - // Scale the sum by the value of B(x) - targetSum = targetSum * numeratorValue; - } - - // Univariate evaluation of the monomial ((1-X_l) + X_l.B_l) at the challenge point X_l=u_l - function partiallyEvaluatePOW(Transcript memory tp, Fr currentEvaluation, Fr roundChallenge, uint256 round) - internal view returns(Fr newEvaluation) - { - Fr univariateEval = Fr.wrap(1) + (roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); - newEvaluation = currentEvaluation * univariateEval; - } - - // Calculate the contributions of each relation to the expected value of the full honk relation - // - // For each relation, we use the purported values ( the ones provided by the prover ) of the multivariates to - // calculate a contribution to the purported value of the full Honk relation. - // These are stored in the evaluations part of the proof object. - // We add these together, with the appropiate scaling factor ( the alphas calculated in challenges ) - // This value is checked against the final value of the target total sum - et voila! function accumulateRelationEvaluations(Honk.Proof memory proof, Transcript memory tp, Fr powPartialEval) - internal view returns(Fr accumulator) + internal + view + returns (Fr accumulator) { Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations = proof.sumcheckEvaluations; Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; - // Accumulate all 6 custom gates - each with varying number of subrelations + // Accumulate all relations in Ultra Honk - each with varying number of subrelations accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); accumulatePermutationRelation(purportedEvaluations, tp, evaluations, powPartialEval); accumulateLogDerivativeLookupRelation(purportedEvaluations, tp, evaluations, powPartialEval); accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); accumulateAuxillaryRelation(purportedEvaluations, tp, evaluations, powPartialEval); - - // Apply alpha challenges to challenge evaluations - // Returns grand honk realtion evaluation + accumulatePoseidonExternalRelation(purportedEvaluations, tp, evaluations, powPartialEval); + accumulatePoseidonInternalRelation(purportedEvaluations, tp, evaluations, powPartialEval); + // batch the subrelations with the alpha challenges to obtain the full honk relation accumulator = scaleAndBatchSubrelations(evaluations, tp.alphas); } @@ -821,8 +565,10 @@ contract HonkVerifier is IVerifier * */ function accumulateArithmeticRelation( - Fr[NUMBER_OF_ENTITIES] memory p, Fr[NUMBER_OF_SUBRELATIONS] memory evals, Fr domainSep) internal view - { + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal view { // Relation 0 Fr q_arith = wire(p, WIRE.Q_ARITH); { @@ -850,9 +596,11 @@ contract HonkVerifier is IVerifier } function accumulatePermutationRelation( - Fr[NUMBER_OF_ENTITIES] memory p, Transcript memory tp, Fr[NUMBER_OF_SUBRELATIONS] memory evals, Fr domainSep) - internal view - { + Fr[NUMBER_OF_ENTITIES] memory p, + Transcript memory tp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { Fr grand_product_numerator; Fr grand_product_denominator; @@ -877,8 +625,11 @@ contract HonkVerifier is IVerifier { Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; - acc = acc - ((wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * tp.publicInputsDelta)) * - grand_product_denominator); + acc = acc + - ( + (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * tp.publicInputsDelta)) + * grand_product_denominator + ); acc = acc * domainSep; evals[2] = acc; } @@ -899,8 +650,8 @@ contract HonkVerifier is IVerifier // Calculate the write term (the table accumulation) { - write_term = wire(p, WIRE.TABLE_1) + tp.gamma + (wire(p, WIRE.TABLE_2) * tp.eta) + - (wire(p, WIRE.TABLE_3) * tp.etaTwo) + (wire(p, WIRE.TABLE_4) * tp.etaThree); + write_term = wire(p, WIRE.TABLE_1) + tp.gamma + (wire(p, WIRE.TABLE_2) * tp.eta) + + (wire(p, WIRE.TABLE_3) * tp.etaTwo) + (wire(p, WIRE.TABLE_4) * tp.etaThree); } // Calculate the write term @@ -909,15 +660,15 @@ contract HonkVerifier is IVerifier Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); - read_term = derived_entry_1 + (derived_entry_2 * tp.eta) + (derived_entry_3 * tp.etaTwo) + - (wire(p, WIRE.Q_O) * tp.etaThree); + read_term = derived_entry_1 + (derived_entry_2 * tp.eta) + (derived_entry_3 * tp.etaTwo) + + (wire(p, WIRE.Q_O) * tp.etaThree); } Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; - Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) - - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); + Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) + - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); // Inverse calculated correctly relation Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; @@ -931,8 +682,10 @@ contract HonkVerifier is IVerifier } function accumulateDeltaRangeRelation( - Fr[NUMBER_OF_ENTITIES] memory p, Fr[NUMBER_OF_SUBRELATIONS] memory evals, Fr domainSep) internal view - { + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal view { Fr minus_one = Fr.wrap(0) - Fr.wrap(1); Fr minus_two = Fr.wrap(0) - Fr.wrap(2); Fr minus_three = Fr.wrap(0) - Fr.wrap(3); @@ -1070,7 +823,6 @@ contract HonkVerifier is IVerifier // Constants for the auxiliary relation Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); - Fr constant MINUS_ONE = Fr.wrap(P - 1); // Parameters used within the Auxiliary Relation // A struct is used to work around stack too deep. This relation has alot of variables @@ -1272,7 +1024,6 @@ contract HonkVerifier is IVerifier Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 - // 1 - ((w3' * eta + w2') * eta + w1') * eta // deg 1 or 4 ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * tp.etaThree; ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * tp.etaTwo); @@ -1335,19 +1086,440 @@ contract HonkVerifier is IVerifier evals[12] = ap.auxiliary_identity; } - function scaleAndBatchSubrelations(Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, - Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges) - internal view returns(Fr accumulator) - { + struct PoseidonExternalParams { + Fr s1; + Fr s2; + Fr s3; + Fr s4; + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr t0; + Fr t1; + Fr t2; + Fr t3; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonExternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Transcript memory tp, // I think this is not needed + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep // i guess this is the scaling factor? + ) internal pure { + PoseidonExternalParams memory ep; + + ep.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + ep.s2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_R); + ep.s3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_O); + ep.s4 = wire(p, WIRE.W_4) + wire(p, WIRE.Q_4); + + ep.u1 = ep.s1 * ep.s1 * ep.s1 * ep.s1 * ep.s1; + ep.u2 = ep.s2 * ep.s2 * ep.s2 * ep.s2 * ep.s2; + ep.u3 = ep.s3 * ep.s3 * ep.s3 * ep.s3 * ep.s3; + ep.u4 = ep.s4 * ep.s4 * ep.s4 * ep.s4 * ep.s4; + // matrix mul v = M_E * u with 14 additions + ep.t0 = ep.u1 + ep.u2; // u_1 + u_2 + ep.t1 = ep.u3 + ep.u4; // u_3 + u_4 + ep.t2 = ep.u2 + ep.u2 + ep.t1; // 2u_2 + // ep.t2 += ep.t1; // 2u_2 + u_3 + u_4 + ep.t3 = ep.u4 + ep.u4 + ep.t0; // 2u_4 + // ep.t3 += ep.t0; // u_1 + u_2 + 2u_4 + ep.v4 = ep.t1 + ep.t1; + ep.v4 = ep.v4 + ep.v4 + ep.t3; + // ep.v4 += ep.t3; // u_1 + u_2 + 4u_3 + 6u_4 + ep.v2 = ep.t0 + ep.t0; + ep.v2 = ep.v2 + ep.v2 + ep.t2; + // ep.v2 += ep.t2; // 4u_1 + 6u_2 + u_3 + u_4 + ep.v1 = ep.t3 + ep.v2; // 5u_1 + 7u_2 + u_3 + 3u_4 + ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4 + + ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep; + evals[18] = evals[18] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT)); + + evals[19] = evals[19] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT)); + + evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT)); + + evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + struct PoseidonInternalParams { + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr u_sum; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr s1; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonInternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Transcript memory tp, // I think this is not needed + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep // i guess this is the scaling factor? + ) internal pure { + PoseidonInternalParams memory ip; + Fr[4] memory INTERNAL_MATRIX_DIAGONAL = [ + FrLib.from(0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7), + FrLib.from(0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b), + FrLib.from(0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15), + FrLib.from(0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b) + ]; + + // add round constants + ip.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + + // apply s-box round + ip.u1 = ip.s1 * ip.s1 * ip.s1 * ip.s1 * ip.s1; + ip.u2 = wire(p, WIRE.W_R); + ip.u3 = wire(p, WIRE.W_O); + ip.u4 = wire(p, WIRE.W_4); + + // matrix mul with v = M_I * u 4 muls and 7 additions + ip.u_sum = ip.u1 + ip.u2 + ip.u3 + ip.u4; + + ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep; + + ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum; + evals[22] = evals[22] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT)); + + ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum; + evals[23] = evals[23] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT)); + + ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum; + evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT)); + + ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum; + evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + function scaleAndBatchSubrelations( + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, + Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges + ) internal pure returns (Fr accumulator) { accumulator = accumulator + evaluations[0]; for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; } } +} + +// Errors +error PublicInputsLengthWrong(); +error SumcheckFailed(); +error ZeromorphFailed(); + +interface IVerifier { + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool); +} + +// Smart contract verifier of honk proofs +contract HonkVerifier is IVerifier +{ + + function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) { + Honk.VerificationKey memory vk = loadVerificationKey(); + Honk.Proof memory p = loadProof(proof); + + if (publicInputs.length != vk.publicInputsSize) { + revert PublicInputsLengthWrong(); + } + + // Generate the fiat shamir challenges for the whole protocol + Transcript memory t = TranscriptLib.generateTranscript(p, publicInputs, vk.publicInputsSize); + + // Compute the public input delta + t.publicInputsDelta = + computePublicInputDelta(publicInputs, t.beta, t.gamma, vk.circuitSize, p.publicInputsOffset); + // Sumcheck + bool sumcheckVerified = verifySumcheck(p, t); + if (!sumcheckVerified) revert SumcheckFailed(); + // Zeromorph + bool zeromorphVerified = verifyZeroMorph(p, vk, t); + if (!zeromorphVerified) revert ZeromorphFailed(); + + return sumcheckVerified && zeromorphVerified; // Boolean condition not required - nice for vanity :) + } + + function loadVerificationKey() internal view returns (Honk.VerificationKey memory) { + return HonkVerificationKey.loadVerificationKey(); + } + + // TODO: mod q proof points + // TODO: Preprocess all of the memory locations + // TODO: Adjust proof point serde away from poseidon forced field elements + function loadProof(bytes calldata proof) internal view returns (Honk.Proof memory) { + Honk.Proof memory p; + + // Metadata + p.circuitSize = uint256(bytes32(proof[0x00:0x20])); + p.publicInputsSize = uint256(bytes32(proof[0x20:0x40])); + p.publicInputsOffset = uint256(bytes32(proof[0x40:0x60])); + + // Commitments + p.w1 = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x60:0x80])), + x_1: uint256(bytes32(proof[0x80:0xa0])), + y_0: uint256(bytes32(proof[0xa0:0xc0])), + y_1: uint256(bytes32(proof[0xc0:0xe0])) + }); + + p.w2 = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0xe0:0x100])), + x_1: uint256(bytes32(proof[0x100:0x120])), + y_0: uint256(bytes32(proof[0x120:0x140])), + y_1: uint256(bytes32(proof[0x140:0x160])) + }); + p.w3 = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x160:0x180])), + x_1: uint256(bytes32(proof[0x180:0x1a0])), + y_0: uint256(bytes32(proof[0x1a0:0x1c0])), + y_1: uint256(bytes32(proof[0x1c0:0x1e0])) + }); + + // Lookup / Permutation Helper Commitments + p.lookupReadCounts = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x1e0:0x200])), + x_1: uint256(bytes32(proof[0x200:0x220])), + y_0: uint256(bytes32(proof[0x220:0x240])), + y_1: uint256(bytes32(proof[0x240:0x260])) + }); + p.lookupReadTags = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x260:0x280])), + x_1: uint256(bytes32(proof[0x280:0x2a0])), + y_0: uint256(bytes32(proof[0x2a0:0x2c0])), + y_1: uint256(bytes32(proof[0x2c0:0x2e0])) + }); + p.w4 = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x2e0:0x300])), + x_1: uint256(bytes32(proof[0x300:0x320])), + y_0: uint256(bytes32(proof[0x320:0x340])), + y_1: uint256(bytes32(proof[0x340:0x360])) + }); + p.lookupInverses = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x360:0x380])), + x_1: uint256(bytes32(proof[0x380:0x3a0])), + y_0: uint256(bytes32(proof[0x3a0:0x3c0])), + y_1: uint256(bytes32(proof[0x3c0:0x3e0])) + }); + p.zPerm = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x3e0:0x400])), + x_1: uint256(bytes32(proof[0x400:0x420])), + y_0: uint256(bytes32(proof[0x420:0x440])), + y_1: uint256(bytes32(proof[0x440:0x460])) + }); + + // TEMP the boundary of what has already been read + uint256 boundary = 0x460; + + // Sumcheck univariates + // TODO: in this case we know what log_n is - so we hard code it, we would want this to be included in + // a cpp template for different circuit sizes + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + // The loop boundary of i, this will shift forward on each evaluation + uint256 loop_boundary = boundary + (i * 0x20 * BATCHED_RELATION_PARTIAL_LENGTH); + + for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { + uint256 start = loop_boundary + (j * 0x20); + uint256 end = start + 0x20; + p.sumcheckUnivariates[i][j] = FrLib.fromBytes32(bytes32(proof[start:end])); + } + } + + boundary = boundary + (CONST_PROOF_SIZE_LOG_N * BATCHED_RELATION_PARTIAL_LENGTH * 0x20); + // Sumcheck evaluations + for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { + uint256 start = boundary + (i * 0x20); + uint256 end = start + 0x20; + p.sumcheckEvaluations[i] = FrLib.fromBytes32(bytes32(proof[start:end])); + } + + boundary = boundary + (NUMBER_OF_ENTITIES * 0x20); + // Zero morph Commitments + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + // Explicitly stating the x0, x1, y0, y1 start and end boundaries to make the calldata slicing bearable + uint256 xStart = boundary + (i * 0x80); + uint256 xEnd = xStart + 0x20; + + uint256 x1Start = xEnd; + uint256 x1End = x1Start + 0x20; + + uint256 yStart = x1End; + uint256 yEnd = yStart + 0x20; + + uint256 y1Start = yEnd; + uint256 y1End = y1Start + 0x20; + + p.zmCqs[i] = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[xStart:xEnd])), + x_1: uint256(bytes32(proof[x1Start:x1End])), + y_0: uint256(bytes32(proof[yStart:yEnd])), + y_1: uint256(bytes32(proof[y1Start:y1End])) + }); + } + + boundary = boundary + (CONST_PROOF_SIZE_LOG_N * 0x80); + + p.zmCq = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[boundary:boundary + 0x20])), + x_1: uint256(bytes32(proof[boundary + 0x20:boundary + 0x40])), + y_0: uint256(bytes32(proof[boundary + 0x40:boundary + 0x60])), + y_1: uint256(bytes32(proof[boundary + 0x60:boundary + 0x80])) + }); + + p.zmPi = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[boundary + 0x80:boundary + 0xa0])), + x_1: uint256(bytes32(proof[boundary + 0xa0:boundary + 0xc0])), + y_0: uint256(bytes32(proof[boundary + 0xc0:boundary + 0xe0])), + y_1: uint256(bytes32(proof[boundary + 0xe0:boundary + 0x100])) + }); + + return p; + } + + function computePublicInputDelta( + bytes32[] memory publicInputs, + Fr beta, + Fr gamma, + uint256 domainSize, + uint256 offset + ) internal view returns (Fr publicInputDelta) { + Fr numerator = Fr.wrap(1); + Fr denominator = Fr.wrap(1); + + Fr numeratorAcc = gamma + (beta * FrLib.from(domainSize + offset)); + Fr denominatorAcc = gamma - (beta * FrLib.from(offset + 1)); + + { + for (uint256 i = 0; i < NUMBER_OF_PUBLIC_INPUTS; i++) { + Fr pubInput = FrLib.fromBytes32(publicInputs[i]); + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + } + + // Fr delta = numerator / denominator; // TOOO: batch invert later? + publicInputDelta = FrLib.div(numerator, denominator); + } + + uint256 constant ROUND_TARGET = 0; + + function verifySumcheck(Honk.Proof memory proof, Transcript memory tp) internal view returns (bool verified) { + Fr roundTarget; + Fr powPartialEvaluation = Fr.wrap(1); + + // We perform sumcheck reductions over log n rounds ( the multivariate degree ) + for (uint256 round; round < LOG_N; ++round) { + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round]; + bool valid = checkSum(roundUnivariate, roundTarget); + if (!valid) revert SumcheckFailed(); + Fr roundChallenge = tp.sumCheckUChallenges[round]; + // Update the round target for the next rounf + roundTarget = computeNextTargetSum(roundUnivariate, roundChallenge); + powPartialEvaluation = partiallyEvaluatePOW(tp, powPartialEvaluation, roundChallenge, round); + } + + // Last round + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations(proof, tp, powPartialEvaluation); + verified = (grandHonkRelationSum == roundTarget); + } + + function checkSum(Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate, Fr roundTarget) + internal + view + returns (bool checked) + { + Fr totalSum = roundUnivariate[0] + roundUnivariate[1]; + checked = totalSum == roundTarget; + } + + // Return the new target sum for the next sumcheck round + function computeNextTargetSum(Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge) + internal + view + returns (Fr targetSum) + { + // TODO: inline + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000002d0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff11), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000090), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff71), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000000f0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000013b0) + ]; + + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_DOMAIN = [ + Fr.wrap(0x00), + Fr.wrap(0x01), + Fr.wrap(0x02), + Fr.wrap(0x03), + Fr.wrap(0x04), + Fr.wrap(0x05), + Fr.wrap(0x06), + Fr.wrap(0x07) + ]; + // To compute the next target sum, we evaluate the given univariate at a point u (challenge). + + // TODO: opt: use same array mem for each iteratioon + // Performing Barycentric evaluations + // Compute B(x) + Fr numeratorValue = Fr.wrap(1); + for (uint256 i; i < BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + numeratorValue = numeratorValue * (roundChallenge - Fr.wrap(i)); + } + + // Calculate domain size N of inverses -- TODO: montgomery's trick + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory denominatorInverses; + for (uint256 i; i < BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + Fr inv = BARYCENTRIC_LAGRANGE_DENOMINATORS[i]; + inv = inv * (roundChallenge - BARYCENTRIC_DOMAIN[i]); + inv = FrLib.invert(inv); + denominatorInverses[i] = inv; + } + + for (uint256 i; i < BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + Fr term = roundUnivariates[i]; + term = term * denominatorInverses[i]; + targetSum = targetSum + term; + } + + // Scale the sum by the value of B(x) + targetSum = targetSum * numeratorValue; + } + + // Univariate evaluation of the monomial ((1-X_l) + X_l.B_l) at the challenge point X_l=u_l + function partiallyEvaluatePOW(Transcript memory tp, Fr currentEvaluation, Fr roundChallenge, uint256 round) + internal + pure + returns (Fr newEvaluation) + { + Fr univariateEval = Fr.wrap(1) + (roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); + newEvaluation = currentEvaluation * univariateEval; + } function verifyZeroMorph(Honk.Proof memory proof, Honk.VerificationKey memory vk, Transcript memory tp) - internal view returns(bool verified) + internal + view + returns (bool verified) { // Construct batched evaluation v = sum_{i=0}^{m-1}\rho^i*f_i(u) + sum_{i=0}^{l-1}\rho^{m+i}*h_i(u) Fr batchedEval = Fr.wrap(0); @@ -1370,8 +1542,7 @@ contract HonkVerifier is IVerifier } // Compute commitment to lifted degree quotient identity - function computeCZeta(Honk.Proof memory proof, Transcript memory tp) internal view returns(Honk.G1Point memory) - { + function computeCZeta(Honk.Proof memory proof, Transcript memory tp) internal view returns (Honk.G1Point memory) { Fr[LOG_N + 1] memory scalars; Honk.G1ProofPoint[LOG_N + 1] memory commitments; @@ -1379,6 +1550,7 @@ contract HonkVerifier is IVerifier commitments[0] = proof.zmCq; scalars[0] = Fr.wrap(1); + // TODO: optimize pow operations here ? batch mulable for (uint256 k = 0; k < LOG_N; ++k) { Fr degree = Fr.wrap((1 << k) - 1); Fr scalar = FrLib.pow(tp.zmY, k); @@ -1405,10 +1577,12 @@ contract HonkVerifier is IVerifier Fr x_pow_2kp1; } - function - computeCZetaX(Honk.Proof memory proof, Honk.VerificationKey memory vk, Transcript memory tp, Fr batchedEval) - internal view returns(Honk.G1Point memory) - { + function computeCZetaX( + Honk.Proof memory proof, + Honk.VerificationKey memory vk, + Transcript memory tp, + Fr batchedEval + ) internal view returns (Honk.G1Point memory) { Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 1] memory scalars; Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 1] memory commitments; CZetaXParams memory cp; @@ -1420,19 +1594,19 @@ contract HonkVerifier is IVerifier // Add contribution: -v * x * \Phi_n(x) * [1]_1 // Add base scalars[0] = MINUS_ONE * batchedEval * tp.zmX * cp.phi_n_x; - commitments[0] = Honk.G1Point({ x : 1, y : 2 }); // One + commitments[0] = Honk.G1Point({x: 1, y: 2}); // One // f - Add all unshifted commitments // g - Add add to be shifted commitments // f commitments are accumulated at (zm_x * r) cp.rho_pow = Fr.wrap(1); - for (uint256 i = 1; i < 34; ++i) { + for (uint256 i = 1; i <= NUMBER_UNSHIFTED; ++i) { scalars[i] = tp.zmX * cp.rho_pow; cp.rho_pow = cp.rho_pow * tp.rho; } // g commitments are accumulated at r - for (uint256 i = 34; i < 43; ++i) { + for (uint256 i = NUMBER_UNSHIFTED + 1; i <= NUMBER_OF_ENTITIES; ++i) { scalars[i] = cp.rho_pow; cp.rho_pow = cp.rho_pow * tp.rho; } @@ -1448,41 +1622,43 @@ contract HonkVerifier is IVerifier commitments[9] = vk.qElliptic; commitments[10] = vk.qAux; commitments[11] = vk.qLookup; - commitments[12] = vk.s1; - commitments[13] = vk.s2; - commitments[14] = vk.s3; - commitments[15] = vk.s4; - commitments[16] = vk.id1; - commitments[17] = vk.id2; - commitments[18] = vk.id3; - commitments[19] = vk.id4; - commitments[20] = vk.t1; - commitments[21] = vk.t2; - commitments[22] = vk.t3; - commitments[23] = vk.t4; - commitments[24] = vk.lagrangeFirst; - commitments[25] = vk.lagrangeLast; + commitments[12] = vk.qPoseidon2External; + commitments[13] = vk.qPoseidon2Internal; + commitments[14] = vk.s1; + commitments[15] = vk.s2; + commitments[16] = vk.s3; + commitments[17] = vk.s4; + commitments[18] = vk.id1; + commitments[19] = vk.id2; + commitments[20] = vk.id3; + commitments[21] = vk.id4; + commitments[22] = vk.t1; + commitments[23] = vk.t2; + commitments[24] = vk.t3; + commitments[25] = vk.t4; + commitments[26] = vk.lagrangeFirst; + commitments[27] = vk.lagrangeLast; // Accumulate proof points - commitments[26] = convertProofPoint(proof.w1); - commitments[27] = convertProofPoint(proof.w2); - commitments[28] = convertProofPoint(proof.w3); - commitments[29] = convertProofPoint(proof.w4); - commitments[30] = convertProofPoint(proof.zPerm); - commitments[31] = convertProofPoint(proof.lookupInverses); - commitments[32] = convertProofPoint(proof.lookupReadCounts); - commitments[33] = convertProofPoint(proof.lookupReadTags); + commitments[28] = convertProofPoint(proof.w1); + commitments[29] = convertProofPoint(proof.w2); + commitments[30] = convertProofPoint(proof.w3); + commitments[31] = convertProofPoint(proof.w4); + commitments[32] = convertProofPoint(proof.zPerm); + commitments[33] = convertProofPoint(proof.lookupInverses); + commitments[34] = convertProofPoint(proof.lookupReadCounts); + commitments[35] = convertProofPoint(proof.lookupReadTags); // to be Shifted - commitments[34] = vk.t1; - commitments[35] = vk.t2; - commitments[36] = vk.t3; - commitments[37] = vk.t4; - commitments[38] = convertProofPoint(proof.w1); - commitments[39] = convertProofPoint(proof.w2); - commitments[40] = convertProofPoint(proof.w3); - commitments[41] = convertProofPoint(proof.w4); - commitments[42] = convertProofPoint(proof.zPerm); + commitments[36] = vk.t1; + commitments[37] = vk.t2; + commitments[38] = vk.t3; + commitments[39] = vk.t4; + commitments[40] = convertProofPoint(proof.w1); + commitments[41] = convertProofPoint(proof.w2); + commitments[42] = convertProofPoint(proof.w3); + commitments[43] = convertProofPoint(proof.w4); + commitments[44] = convertProofPoint(proof.zPerm); // Add scalar contributions // Add contributions: scalar * [q_k], k = 0,...,log_N, where @@ -1507,8 +1683,8 @@ contract HonkVerifier is IVerifier cp.x_pow_2kp1 = cp.x_pow_2kp1 * cp.x_pow_2kp1; } - scalars[43 + k] = scalar; - commitments[43 + k] = convertProofPoint(proof.zmCqs[k]); + scalars[NUMBER_OF_ENTITIES + 1 + k] = scalar; + commitments[NUMBER_OF_ENTITIES + 1 + k] = convertProofPoint(proof.zmCqs[k]); } return batchMul2(commitments, scalars); @@ -1516,11 +1692,12 @@ contract HonkVerifier is IVerifier // Scalar Mul and acumulate into total function batchMul(Honk.G1Point[LOG_N + 1] memory base, Fr[LOG_N + 1] memory scalars) - internal view returns(Honk.G1Point memory result) + internal + view + returns (Honk.G1Point memory result) { uint256 limit = LOG_N + 1; - assembly - { + assembly { let success := 0x01 let free := mload(0x40) @@ -1534,9 +1711,10 @@ contract HonkVerifier is IVerifier success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, free, 0x40)) let count := 0x01 + for {} lt(count, limit) { count := add(count, 1) } { // Get loop offsets - let base_base := add(base, mul(count, 0x20)) + let base_base := add(base, mul(count, 0x20)) let scalar_base := add(scalars, mul(count, 0x20)) mstore(add(free, 0x40), mload(mload(base_base))) @@ -1544,22 +1722,22 @@ contract HonkVerifier is IVerifier // Add scalar mstore(add(free, 0x80), mload(scalar_base)) - success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40)) } - mstore(result, mload(free)) mstore(add(result, 0x20), mload(add(free, 0x20))) + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) } } // This implementation is the same as above with different constants - function batchMul2(Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 1] memory base, - Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 1] memory scalars) - internal view returns(Honk.G1Point memory result) - { + function batchMul2( + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 1] memory base, + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 1] memory scalars + ) internal view returns (Honk.G1Point memory result) { uint256 limit = NUMBER_OF_ENTITIES + LOG_N + 1; - assembly - { + assembly { let success := 0x01 let free := mload(0x40) @@ -1573,9 +1751,9 @@ contract HonkVerifier is IVerifier success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, free, 0x40)) let count := 0x01 - for {} lt(count, limit){ count := add(count, 1) } { + for {} lt(count, limit) { count := add(count, 1) } { // Get loop offsets - let base_base := add(base, mul(count, 0x20)) + let base_base := add(base, mul(count, 0x20)) let scalar_base := add(scalars, mul(count, 0x20)) mstore(add(free, 0x40), mload(mload(base_base))) @@ -1584,21 +1762,24 @@ contract HonkVerifier is IVerifier mstore(add(free, 0x80), mload(scalar_base)) success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) - // accumulator = accumulator + accumulator_2 + // accumulator = accumulator + accumulator_2 success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40)) } // Return the result - i hate this - mstore(result, mload(free)) mstore(add(result, 0x20), mload(add(free, 0x20))) + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) } } function zkgReduceVerify( - Honk.Proof memory proof, Transcript memory tp, Fr evaluation, Honk.G1Point memory commitment) - internal view returns(bool) - { + Honk.Proof memory proof, + Transcript memory tp, + Fr evaluation, + Honk.G1Point memory commitment + ) internal view returns (bool) { Honk.G1Point memory quotient_commitment = convertProofPoint(proof.zmPi); - Honk.G1Point memory ONE = Honk.G1Point({ x : 1, y : 2 }); + Honk.G1Point memory ONE = Honk.G1Point({x: 1, y: 2}); Honk.G1Point memory P0 = commitment; P0 = ecAdd(P0, ecMul(quotient_commitment, tp.zmX)); @@ -1636,8 +1817,9 @@ contract HonkVerifier is IVerifier } // Conversion util - Duplicated as we cannot template LOG_N -function convertPoints(Honk.G1ProofPoint[LOG_N + 1] memory commitments) pure - returns(Honk.G1Point[LOG_N + 1] memory converted) +function convertPoints(Honk.G1ProofPoint[LOG_N + 1] memory commitments) + pure + returns (Honk.G1Point[LOG_N + 1] memory converted) { for (uint256 i; i < LOG_N + 1; ++i) { converted[i] = convertProofPoint(commitments[i]); diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fq.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fq.hpp index dce9f2634e9..29b6aa99eda 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fq.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fq.hpp @@ -106,6 +106,7 @@ class Bn254FqParams { // The modulus is larger than BN254 scalar field modulus, so it maps to two BN254 scalars static constexpr size_t NUM_BN254_SCALARS = 2; + static constexpr size_t MAX_BITS_PER_ENDOMORPHISM_SCALAR = 128; }; using fq = field; diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fr.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fr.hpp index fcf2bc16a55..4d414618066 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fr.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fr.hpp @@ -112,6 +112,7 @@ class Bn254FrParams { // This is a BN254 scalar, so it represents one BN254 scalar static constexpr size_t NUM_BN254_SCALARS = 1; + static constexpr size_t MAX_BITS_PER_ENDOMORPHISM_SCALAR = 128; }; using fr = field; diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp index fa3dfe2864a..6a92624af5e 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp @@ -93,7 +93,7 @@ std::vector convert_grumpkin_fr_to_bn254_frs(const grumpkin::fr& val); */ template std::vector convert_to_bn254_frs(const T& val) { - if constexpr (IsAnyOf) { + if constexpr (IsAnyOf) { std::vector fr_vec{ val }; return fr_vec; } else if constexpr (IsAnyOf) { diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp index cba9f21da56..17f0113101d 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp @@ -174,8 +174,8 @@ template struct alignas(32) field { constexpr field(const field& other) noexcept = default; constexpr field(field&& other) noexcept = default; - constexpr field& operator=(const field& other) noexcept = default; - constexpr field& operator=(field&& other) noexcept = default; + constexpr field& operator=(const field& other) & noexcept = default; + constexpr field& operator=(field&& other) & noexcept = default; constexpr ~field() noexcept = default; alignas(32) uint64_t data[4]; // NOLINT @@ -298,10 +298,10 @@ template struct alignas(32) field { // NOLINTNEXTLINE BB_INLINE constexpr field operator++(int) noexcept; - BB_INLINE constexpr field& operator*=(const field& other) noexcept; - BB_INLINE constexpr field& operator+=(const field& other) noexcept; - BB_INLINE constexpr field& operator-=(const field& other) noexcept; - constexpr field& operator/=(const field& other) noexcept; + BB_INLINE constexpr field& operator*=(const field& other) & noexcept; + BB_INLINE constexpr field& operator+=(const field& other) & noexcept; + BB_INLINE constexpr field& operator-=(const field& other) & noexcept; + constexpr field& operator/=(const field& other) & noexcept; // NOTE: comparison operators exist so that `field` is comparible with stl methods that require them. // (e.g. std::sort) @@ -315,7 +315,7 @@ template struct alignas(32) field { BB_INLINE constexpr field from_montgomery_form() const noexcept; BB_INLINE constexpr field sqr() const noexcept; - BB_INLINE constexpr void self_sqr() noexcept; + BB_INLINE constexpr void self_sqr() & noexcept; BB_INLINE constexpr field pow(const uint256_t& exponent) const noexcept; BB_INLINE constexpr field pow(uint64_t exponent) const noexcept; @@ -332,17 +332,17 @@ template struct alignas(32) field { */ constexpr std::pair sqrt() const noexcept; - BB_INLINE constexpr void self_neg() noexcept; + BB_INLINE constexpr void self_neg() & noexcept; - BB_INLINE constexpr void self_to_montgomery_form() noexcept; - BB_INLINE constexpr void self_from_montgomery_form() noexcept; + BB_INLINE constexpr void self_to_montgomery_form() & noexcept; + BB_INLINE constexpr void self_from_montgomery_form() & noexcept; - BB_INLINE constexpr void self_conditional_negate(uint64_t predicate) noexcept; + BB_INLINE constexpr void self_conditional_negate(uint64_t predicate) & noexcept; BB_INLINE constexpr field reduce_once() const noexcept; - BB_INLINE constexpr void self_reduce_once() noexcept; + BB_INLINE constexpr void self_reduce_once() & noexcept; - BB_INLINE constexpr void self_set_msb() noexcept; + BB_INLINE constexpr void self_set_msb() & noexcept; [[nodiscard]] BB_INLINE constexpr bool is_msb_set() const noexcept; [[nodiscard]] BB_INLINE constexpr uint64_t is_msb_set_word() const noexcept; diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_impl.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_impl.hpp index 1c556fa43de..7f92fd299c1 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_impl.hpp @@ -39,7 +39,7 @@ template constexpr field field::operator*(const field& other) co } } -template constexpr field& field::operator*=(const field& other) noexcept +template constexpr field& field::operator*=(const field& other) & noexcept { BB_OP_COUNT_TRACK_NAME("fr::self_mul"); if constexpr (BBERG_NO_ASM || (T::modulus_3 >= 0x4000000000000000ULL) || @@ -75,7 +75,7 @@ template constexpr field field::sqr() const noexcept } } -template constexpr void field::self_sqr() noexcept +template constexpr void field::self_sqr() & noexcept { BB_OP_COUNT_TRACK_NAME("f::self_sqr"); if constexpr (BBERG_NO_ASM || (T::modulus_3 >= 0x4000000000000000ULL) || @@ -109,7 +109,7 @@ template constexpr field field::operator+(const field& other) co } } -template constexpr field& field::operator+=(const field& other) noexcept +template constexpr field& field::operator+=(const field& other) & noexcept { BB_OP_COUNT_TRACK_NAME("fr::self_add"); if constexpr (BBERG_NO_ASM || (T::modulus_3 >= 0x4000000000000000ULL) || @@ -188,7 +188,7 @@ template constexpr field field::operator-() const noexcept return (p - *this).reduce_once(); // modulus - *this; } -template constexpr field& field::operator-=(const field& other) noexcept +template constexpr field& field::operator-=(const field& other) & noexcept { BB_OP_COUNT_TRACK_NAME("fr::self_sub"); if constexpr (BBERG_NO_ASM || (T::modulus_3 >= 0x4000000000000000ULL) || @@ -204,7 +204,7 @@ template constexpr field& field::operator-=(const field& other) return *this; } -template constexpr void field::self_neg() noexcept +template constexpr void field::self_neg() & noexcept { BB_OP_COUNT_TRACK_NAME("fr::self_neg"); if constexpr ((T::modulus_3 >= 0x4000000000000000ULL) || @@ -217,7 +217,7 @@ template constexpr void field::self_neg() noexcept } } -template constexpr void field::self_conditional_negate(const uint64_t predicate) noexcept +template constexpr void field::self_conditional_negate(const uint64_t predicate) & noexcept { BB_OP_COUNT_TRACK_NAME("fr::self_conditional_negate"); if constexpr (BBERG_NO_ASM || (T::modulus_3 >= 0x4000000000000000ULL) || @@ -313,7 +313,7 @@ template constexpr field field::from_montgomery_form() const noe return operator*(one_raw).reduce_once(); } -template constexpr void field::self_to_montgomery_form() noexcept +template constexpr void field::self_to_montgomery_form() & noexcept { BB_OP_COUNT_TRACK_NAME("fr::self_to_montgomery_form"); constexpr field r_squared = @@ -326,7 +326,7 @@ template constexpr void field::self_to_montgomery_form() noexcept self_reduce_once(); } -template constexpr void field::self_from_montgomery_form() noexcept +template constexpr void field::self_from_montgomery_form() & noexcept { BB_OP_COUNT_TRACK_NAME("fr::self_from_montgomery_form"); constexpr field one_raw{ 1, 0, 0, 0 }; @@ -348,7 +348,7 @@ template constexpr field field::reduce_once() const noexcept } } -template constexpr void field::self_reduce_once() noexcept +template constexpr void field::self_reduce_once() & noexcept { BB_OP_COUNT_TRACK_NAME("fr::self_reduce_once"); if constexpr (BBERG_NO_ASM || (T::modulus_3 >= 0x4000000000000000ULL) || @@ -555,14 +555,14 @@ template constexpr field field::operator/(const field& other) co return operator*(other.invert()); } -template constexpr field& field::operator/=(const field& other) noexcept +template constexpr field& field::operator/=(const field& other) & noexcept { BB_OP_COUNT_TRACK_NAME("fr::self_div"); *this = operator/(other); return *this; } -template constexpr void field::self_set_msb() noexcept +template constexpr void field::self_set_msb() & noexcept { data[3] = 0ULL | (1ULL << 63ULL); } diff --git a/barretenberg/cpp/src/barretenberg/ecc/groups/element.hpp b/barretenberg/cpp/src/barretenberg/ecc/groups/element.hpp index 4203bfdf4dd..d76c6204344 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/groups/element.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/groups/element.hpp @@ -95,7 +95,7 @@ template class alignas(32) element { const std::span>& second_group, const std::span>& results) noexcept; static std::vector> batch_mul_with_endomorphism( - const std::span>& points, const Fr& scalar) noexcept; + const std::span>& points, const Fr& scalar) noexcept; Fq x; Fq y; diff --git a/barretenberg/cpp/src/barretenberg/ecc/groups/element_impl.hpp b/barretenberg/cpp/src/barretenberg/ecc/groups/element_impl.hpp index 6630406b89a..25d460ac5a7 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/groups/element_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/groups/element_impl.hpp @@ -790,7 +790,7 @@ void element::batch_affine_add(const std::span std::vector> element::batch_mul_with_endomorphism( - const std::span>& points, const Fr& scalar) noexcept + const std::span>& points, const Fr& scalar) noexcept { BB_OP_COUNT_TIME(); typedef affine_element affine_element; diff --git a/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/scalar_multiplication.cpp b/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/scalar_multiplication.cpp index 2b6e6625630..b4a3866d2d0 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/scalar_multiplication.cpp +++ b/barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/scalar_multiplication.cpp @@ -342,7 +342,8 @@ void add_affine_points(typename Curve::AffineElement* points, } if (batch_inversion_accumulator == 0) { - throw_or_abort("attempted to invert zero in add_affine_points"); + // prefer abort to throw for code that might emit from multiple threads + abort_with_message("attempted to invert zero in add_affine_points"); } else { batch_inversion_accumulator = batch_inversion_accumulator.invert(); } @@ -894,7 +895,7 @@ typename Curve::Element pippenger(std::span s pippenger_runtime_state& state, bool handle_edge_cases) { - BB_OP_COUNT_TRACK(); + BB_OP_COUNT_TIME_NAME("pippenger"); using Group = typename Curve::Group; using Element = typename Curve::Element; @@ -955,7 +956,7 @@ typename Curve::Element pippenger_unsafe_optimized_for_non_dyadic_polys( return pippenger_unsafe(scalars, points, state); } // We need a padding of scalars. - ASSERT(numeric::round_up_power_2(scalars.size()) <= points.size()); + ASSERT(numeric::round_up_power_2(scalars.size()) * 2 <= points.size()); // We do not optimize for the small case at all. return pippenger_internal(points, scalars, numeric::round_up_power_2(scalars.size()), state, false); } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp index 4d70b0c3110..8ffc37964e9 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp @@ -383,7 +383,7 @@ class ECCVMFlavor { * @brief Returns the evaluations of all prover polynomials at one point on the boolean hypercube, which * represents one row in the execution trace. */ - AllValues get_row(const size_t row_idx) + AllValues get_row(const size_t row_idx) const { AllValues result; for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) { @@ -505,13 +505,20 @@ class ECCVMFlavor { const auto log_num_rows = static_cast(numeric::get_msb64(num_rows)); const size_t dyadic_num_rows = 1UL << (log_num_rows + (1UL << log_num_rows == num_rows ? 0 : 1)); + for (auto& poly : get_to_be_shifted()) { + poly = Polynomial{ /*memory size*/ dyadic_num_rows - 1, + /*largest possible index*/ dyadic_num_rows, + /* offset */ 1 }; + } // allocate polynomials; define lagrange and lookup read count polynomials for (auto& poly : get_all()) { - poly = Polynomial(dyadic_num_rows); + if (poly.is_empty()) { + poly = Polynomial(dyadic_num_rows); + } } - lagrange_first[0] = 1; - lagrange_second[1] = 1; - lagrange_last[lagrange_last.size() - 1] = 1; + lagrange_first.at(0) = 1; + lagrange_second.at(1) = 1; + lagrange_last.at(lagrange_last.size() - 1) = 1; for (size_t i = 0; i < point_table_read_counts[0].size(); ++i) { // Explanation of off-by-one offset: // When computing the WNAF slice for a point at point counter value `pc` and a round index `round`, the @@ -519,44 +526,48 @@ class ECCVMFlavor { // `lookup_read_counts`. We do this mapping in `ecc_msm_relation`. We are off-by-one because we add an // empty row at the start of the WNAF columns that is not accounted for (index of lookup_read_counts // maps to the row in our WNAF columns that computes a slice for a given value of pc and round) - lookup_read_counts_0[i + 1] = point_table_read_counts[0][i]; - lookup_read_counts_1[i + 1] = point_table_read_counts[1][i]; + lookup_read_counts_0.at(i + 1) = point_table_read_counts[0][i]; + lookup_read_counts_1.at(i + 1) = point_table_read_counts[1][i]; } // compute polynomials for transcript columns parallel_for_range(transcript_rows.size(), [&](size_t start, size_t end) { for (size_t i = start; i < end; i++) { - transcript_accumulator_empty[i] = transcript_rows[i].accumulator_empty; - transcript_add[i] = transcript_rows[i].q_add; - transcript_mul[i] = transcript_rows[i].q_mul; - transcript_eq[i] = transcript_rows[i].q_eq; - transcript_reset_accumulator[i] = transcript_rows[i].q_reset_accumulator; - transcript_msm_transition[i] = transcript_rows[i].msm_transition; - transcript_pc[i] = transcript_rows[i].pc; - transcript_msm_count[i] = transcript_rows[i].msm_count; - transcript_Px[i] = transcript_rows[i].base_x; - transcript_Py[i] = transcript_rows[i].base_y; - transcript_z1[i] = transcript_rows[i].z1; - transcript_z2[i] = transcript_rows[i].z2; - transcript_z1zero[i] = transcript_rows[i].z1_zero; - transcript_z2zero[i] = transcript_rows[i].z2_zero; - transcript_op[i] = transcript_rows[i].opcode; - transcript_accumulator_x[i] = transcript_rows[i].accumulator_x; - transcript_accumulator_y[i] = transcript_rows[i].accumulator_y; - transcript_msm_x[i] = transcript_rows[i].msm_output_x; - transcript_msm_y[i] = transcript_rows[i].msm_output_y; - transcript_base_infinity[i] = transcript_rows[i].base_infinity; - transcript_base_x_inverse[i] = transcript_rows[i].base_x_inverse; - transcript_base_y_inverse[i] = transcript_rows[i].base_y_inverse; - transcript_add_x_equal[i] = transcript_rows[i].transcript_add_x_equal; - transcript_add_y_equal[i] = transcript_rows[i].transcript_add_y_equal; - transcript_add_lambda[i] = transcript_rows[i].transcript_add_lambda; - transcript_msm_intermediate_x[i] = transcript_rows[i].transcript_msm_intermediate_x; - transcript_msm_intermediate_y[i] = transcript_rows[i].transcript_msm_intermediate_y; - transcript_msm_infinity[i] = transcript_rows[i].transcript_msm_infinity; - transcript_msm_x_inverse[i] = transcript_rows[i].transcript_msm_x_inverse; - transcript_msm_count_zero_at_transition[i] = transcript_rows[i].msm_count_zero_at_transition; - transcript_msm_count_at_transition_inverse[i] = transcript_rows[i].msm_count_at_transition_inverse; + transcript_accumulator_empty.set_if_valid_index(i, transcript_rows[i].accumulator_empty); + transcript_add.set_if_valid_index(i, transcript_rows[i].q_add); + transcript_mul.set_if_valid_index(i, transcript_rows[i].q_mul); + transcript_eq.set_if_valid_index(i, transcript_rows[i].q_eq); + transcript_reset_accumulator.set_if_valid_index(i, transcript_rows[i].q_reset_accumulator); + transcript_msm_transition.set_if_valid_index(i, transcript_rows[i].msm_transition); + transcript_pc.set_if_valid_index(i, transcript_rows[i].pc); + transcript_msm_count.set_if_valid_index(i, transcript_rows[i].msm_count); + transcript_Px.set_if_valid_index(i, transcript_rows[i].base_x); + transcript_Py.set_if_valid_index(i, transcript_rows[i].base_y); + transcript_z1.set_if_valid_index(i, transcript_rows[i].z1); + transcript_z2.set_if_valid_index(i, transcript_rows[i].z2); + transcript_z1zero.set_if_valid_index(i, transcript_rows[i].z1_zero); + transcript_z2zero.set_if_valid_index(i, transcript_rows[i].z2_zero); + transcript_op.set_if_valid_index(i, transcript_rows[i].opcode); + transcript_accumulator_x.set_if_valid_index(i, transcript_rows[i].accumulator_x); + transcript_accumulator_y.set_if_valid_index(i, transcript_rows[i].accumulator_y); + transcript_msm_x.set_if_valid_index(i, transcript_rows[i].msm_output_x); + transcript_msm_y.set_if_valid_index(i, transcript_rows[i].msm_output_y); + transcript_base_infinity.set_if_valid_index(i, transcript_rows[i].base_infinity); + transcript_base_x_inverse.set_if_valid_index(i, transcript_rows[i].base_x_inverse); + transcript_base_y_inverse.set_if_valid_index(i, transcript_rows[i].base_y_inverse); + transcript_add_x_equal.set_if_valid_index(i, transcript_rows[i].transcript_add_x_equal); + transcript_add_y_equal.set_if_valid_index(i, transcript_rows[i].transcript_add_y_equal); + transcript_add_lambda.set_if_valid_index(i, transcript_rows[i].transcript_add_lambda); + transcript_msm_intermediate_x.set_if_valid_index(i, + transcript_rows[i].transcript_msm_intermediate_x); + transcript_msm_intermediate_y.set_if_valid_index(i, + transcript_rows[i].transcript_msm_intermediate_y); + transcript_msm_infinity.set_if_valid_index(i, transcript_rows[i].transcript_msm_infinity); + transcript_msm_x_inverse.set_if_valid_index(i, transcript_rows[i].transcript_msm_x_inverse); + transcript_msm_count_zero_at_transition.set_if_valid_index( + i, transcript_rows[i].msm_count_zero_at_transition); + transcript_msm_count_at_transition_inverse.set_if_valid_index( + i, transcript_rows[i].msm_count_at_transition_inverse); } }); @@ -565,14 +576,14 @@ class ECCVMFlavor { // values that are all zero (issue #2217) if (transcript_rows[transcript_rows.size() - 1].accumulator_empty) { for (size_t i = transcript_rows.size(); i < dyadic_num_rows; ++i) { - transcript_accumulator_empty[i] = 1; + transcript_accumulator_empty.set_if_valid_index(i, 1); } } // in addition, unless the accumulator is reset, it contains the value from the previous row so this // must be propagated for (size_t i = transcript_rows.size(); i < dyadic_num_rows; ++i) { - transcript_accumulator_x[i] = transcript_accumulator_x[i - 1]; - transcript_accumulator_y[i] = transcript_accumulator_y[i - 1]; + transcript_accumulator_x.set_if_valid_index(i, transcript_accumulator_x[i - 1]); + transcript_accumulator_y.set_if_valid_index(i, transcript_accumulator_y[i - 1]); } parallel_for_range(point_table_rows.size(), [&](size_t start, size_t end) { @@ -580,67 +591,68 @@ class ECCVMFlavor { // first row is always an empty row (to accommodate shifted polynomials which must have 0 as 1st // coefficient). All other rows in the point_table_rows represent active wnaf gates (i.e. // precompute_select = 1) - precompute_select[i] = (i != 0) ? 1 : 0; - precompute_pc[i] = point_table_rows[i].pc; - precompute_point_transition[i] = static_cast(point_table_rows[i].point_transition); - precompute_round[i] = point_table_rows[i].round; - precompute_scalar_sum[i] = point_table_rows[i].scalar_sum; - precompute_s1hi[i] = point_table_rows[i].s1; - precompute_s1lo[i] = point_table_rows[i].s2; - precompute_s2hi[i] = point_table_rows[i].s3; - precompute_s2lo[i] = point_table_rows[i].s4; - precompute_s3hi[i] = point_table_rows[i].s5; - precompute_s3lo[i] = point_table_rows[i].s6; - precompute_s4hi[i] = point_table_rows[i].s7; - precompute_s4lo[i] = point_table_rows[i].s8; + precompute_select.set_if_valid_index(i, (i != 0) ? 1 : 0); + precompute_pc.set_if_valid_index(i, point_table_rows[i].pc); + precompute_point_transition.set_if_valid_index( + i, static_cast(point_table_rows[i].point_transition)); + precompute_round.set_if_valid_index(i, point_table_rows[i].round); + precompute_scalar_sum.set_if_valid_index(i, point_table_rows[i].scalar_sum); + precompute_s1hi.set_if_valid_index(i, point_table_rows[i].s1); + precompute_s1lo.set_if_valid_index(i, point_table_rows[i].s2); + precompute_s2hi.set_if_valid_index(i, point_table_rows[i].s3); + precompute_s2lo.set_if_valid_index(i, point_table_rows[i].s4); + precompute_s3hi.set_if_valid_index(i, point_table_rows[i].s5); + precompute_s3lo.set_if_valid_index(i, point_table_rows[i].s6); + precompute_s4hi.set_if_valid_index(i, point_table_rows[i].s7); + precompute_s4lo.set_if_valid_index(i, point_table_rows[i].s8); // If skew is active (i.e. we need to subtract a base point from the msm result), // write `7` into rows.precompute_skew. `7`, in binary representation, equals `-1` when converted // into WNAF form - precompute_skew[i] = point_table_rows[i].skew ? 7 : 0; - precompute_dx[i] = point_table_rows[i].precompute_double.x; - precompute_dy[i] = point_table_rows[i].precompute_double.y; - precompute_tx[i] = point_table_rows[i].precompute_accumulator.x; - precompute_ty[i] = point_table_rows[i].precompute_accumulator.y; + precompute_skew.set_if_valid_index(i, point_table_rows[i].skew ? 7 : 0); + precompute_dx.set_if_valid_index(i, point_table_rows[i].precompute_double.x); + precompute_dy.set_if_valid_index(i, point_table_rows[i].precompute_double.y); + precompute_tx.set_if_valid_index(i, point_table_rows[i].precompute_accumulator.x); + precompute_ty.set_if_valid_index(i, point_table_rows[i].precompute_accumulator.y); } }); // compute polynomials for the msm columns parallel_for_range(msm_rows.size(), [&](size_t start, size_t end) { for (size_t i = start; i < end; i++) { - msm_transition[i] = static_cast(msm_rows[i].msm_transition); - msm_add[i] = static_cast(msm_rows[i].q_add); - msm_double[i] = static_cast(msm_rows[i].q_double); - msm_skew[i] = static_cast(msm_rows[i].q_skew); - msm_accumulator_x[i] = msm_rows[i].accumulator_x; - msm_accumulator_y[i] = msm_rows[i].accumulator_y; - msm_pc[i] = msm_rows[i].pc; - msm_size_of_msm[i] = msm_rows[i].msm_size; - msm_count[i] = msm_rows[i].msm_count; - msm_round[i] = msm_rows[i].msm_round; - msm_add1[i] = static_cast(msm_rows[i].add_state[0].add); - msm_add2[i] = static_cast(msm_rows[i].add_state[1].add); - msm_add3[i] = static_cast(msm_rows[i].add_state[2].add); - msm_add4[i] = static_cast(msm_rows[i].add_state[3].add); - msm_x1[i] = msm_rows[i].add_state[0].point.x; - msm_y1[i] = msm_rows[i].add_state[0].point.y; - msm_x2[i] = msm_rows[i].add_state[1].point.x; - msm_y2[i] = msm_rows[i].add_state[1].point.y; - msm_x3[i] = msm_rows[i].add_state[2].point.x; - msm_y3[i] = msm_rows[i].add_state[2].point.y; - msm_x4[i] = msm_rows[i].add_state[3].point.x; - msm_y4[i] = msm_rows[i].add_state[3].point.y; - msm_collision_x1[i] = msm_rows[i].add_state[0].collision_inverse; - msm_collision_x2[i] = msm_rows[i].add_state[1].collision_inverse; - msm_collision_x3[i] = msm_rows[i].add_state[2].collision_inverse; - msm_collision_x4[i] = msm_rows[i].add_state[3].collision_inverse; - msm_lambda1[i] = msm_rows[i].add_state[0].lambda; - msm_lambda2[i] = msm_rows[i].add_state[1].lambda; - msm_lambda3[i] = msm_rows[i].add_state[2].lambda; - msm_lambda4[i] = msm_rows[i].add_state[3].lambda; - msm_slice1[i] = msm_rows[i].add_state[0].slice; - msm_slice2[i] = msm_rows[i].add_state[1].slice; - msm_slice3[i] = msm_rows[i].add_state[2].slice; - msm_slice4[i] = msm_rows[i].add_state[3].slice; + msm_transition.set_if_valid_index(i, static_cast(msm_rows[i].msm_transition)); + msm_add.set_if_valid_index(i, static_cast(msm_rows[i].q_add)); + msm_double.set_if_valid_index(i, static_cast(msm_rows[i].q_double)); + msm_skew.set_if_valid_index(i, static_cast(msm_rows[i].q_skew)); + msm_accumulator_x.set_if_valid_index(i, msm_rows[i].accumulator_x); + msm_accumulator_y.set_if_valid_index(i, msm_rows[i].accumulator_y); + msm_pc.set_if_valid_index(i, msm_rows[i].pc); + msm_size_of_msm.set_if_valid_index(i, msm_rows[i].msm_size); + msm_count.set_if_valid_index(i, msm_rows[i].msm_count); + msm_round.set_if_valid_index(i, msm_rows[i].msm_round); + msm_add1.set_if_valid_index(i, static_cast(msm_rows[i].add_state[0].add)); + msm_add2.set_if_valid_index(i, static_cast(msm_rows[i].add_state[1].add)); + msm_add3.set_if_valid_index(i, static_cast(msm_rows[i].add_state[2].add)); + msm_add4.set_if_valid_index(i, static_cast(msm_rows[i].add_state[3].add)); + msm_x1.set_if_valid_index(i, msm_rows[i].add_state[0].point.x); + msm_y1.set_if_valid_index(i, msm_rows[i].add_state[0].point.y); + msm_x2.set_if_valid_index(i, msm_rows[i].add_state[1].point.x); + msm_y2.set_if_valid_index(i, msm_rows[i].add_state[1].point.y); + msm_x3.set_if_valid_index(i, msm_rows[i].add_state[2].point.x); + msm_y3.set_if_valid_index(i, msm_rows[i].add_state[2].point.y); + msm_x4.set_if_valid_index(i, msm_rows[i].add_state[3].point.x); + msm_y4.set_if_valid_index(i, msm_rows[i].add_state[3].point.y); + msm_collision_x1.set_if_valid_index(i, msm_rows[i].add_state[0].collision_inverse); + msm_collision_x2.set_if_valid_index(i, msm_rows[i].add_state[1].collision_inverse); + msm_collision_x3.set_if_valid_index(i, msm_rows[i].add_state[2].collision_inverse); + msm_collision_x4.set_if_valid_index(i, msm_rows[i].add_state[3].collision_inverse); + msm_lambda1.set_if_valid_index(i, msm_rows[i].add_state[0].lambda); + msm_lambda2.set_if_valid_index(i, msm_rows[i].add_state[1].lambda); + msm_lambda3.set_if_valid_index(i, msm_rows[i].add_state[2].lambda); + msm_lambda4.set_if_valid_index(i, msm_rows[i].add_state[3].lambda); + msm_slice1.set_if_valid_index(i, msm_rows[i].add_state[0].slice); + msm_slice2.set_if_valid_index(i, msm_rows[i].add_state[1].slice); + msm_slice3.set_if_valid_index(i, msm_rows[i].add_state[2].slice); + msm_slice4.set_if_valid_index(i, msm_rows[i].add_state[3].slice); } }); this->set_shifted(); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index 2bfc2b565ed..76a64e54fd6 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -135,7 +135,7 @@ void ECCVMProver::execute_pcs_rounds() // TODO(https://github.com/AztecProtocol/barretenberg/issues/768): fix IPA to avoid the need for the hack polynomial Polynomial hack(key->circuit_size); for (size_t idx = 0; idx < key->circuit_size; idx++) { - hack[idx] = 1; + hack.at(idx) = 1; } transcript->send_to_verifier("Translation:hack_commitment", commitment_key->commit(hack)); diff --git a/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.cpp b/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.cpp index 3b861421b47..70146181fcc 100644 --- a/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.cpp @@ -3,7 +3,7 @@ #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_keccak.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_keccak_flavor.hpp" namespace bb { template @@ -64,17 +64,7 @@ typename ExecutionTrace_::TraceData ExecutionTrace_::construct_t uint32_t offset = Flavor::has_zero_row ? 1 : 0; // Offset at which to place each block in the trace polynomials // For each block in the trace, populate wire polys, copy cycles and selector polys - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1078): remove when Keccak flavor works with Poseidon - // gate - auto get_blocks = [&]() { - if constexpr (!HasKeccak) { - return builder.blocks.get(); - } else { - return builder.blocks.get_for_ultra_keccak(); - } - }; - - for (auto& block : get_blocks()) { + for (auto& block : builder.blocks.get()) { auto block_size = static_cast(block.size()); // Update wire polynomials and copy cycles @@ -87,7 +77,7 @@ typename ExecutionTrace_::TraceData ExecutionTrace_::construct_t uint32_t real_var_idx = builder.real_variable_index[var_idx]; uint32_t trace_row_idx = block_row_idx + offset; // Insert the real witness values from this block into the wire polys at the correct offset - trace_data.wires[wire_idx][trace_row_idx] = builder.get_variable(var_idx); + trace_data.wires[wire_idx].at(trace_row_idx) = builder.get_variable(var_idx); // Add the address of the witness value to its corresponding copy cycle trace_data.copy_cycles[real_var_idx].emplace_back(cycle_node{ wire_idx, trace_row_idx }); } @@ -96,12 +86,12 @@ typename ExecutionTrace_::TraceData ExecutionTrace_::construct_t // Insert the selector values for this block into the selector polynomials at the correct offset // TODO(https://github.com/AztecProtocol/barretenberg/issues/398): implicit arithmetization/flavor consistency - for (size_t selector_idx = 0; selector_idx < NUM_USED_SELECTORS; selector_idx++) { + for (size_t selector_idx = 0; selector_idx < NUM_SELECTORS; selector_idx++) { auto selector_poly = trace_data.selectors[selector_idx]; auto selector = block.selectors[selector_idx]; for (size_t row_idx = 0; row_idx < block_size; ++row_idx) { size_t trace_row_idx = row_idx + offset; - trace_data.selectors[selector_idx][trace_row_idx] = selector[row_idx]; + trace_data.selectors[selector_idx].set_if_valid_index(trace_row_idx, selector[row_idx]); } } @@ -115,11 +105,8 @@ typename ExecutionTrace_::TraceData ExecutionTrace_::construct_t } // If the trace is structured, we populate the data from the next block at a fixed block size offset - if (is_structured) { - offset += block.get_fixed_size(); - } else { // otherwise, the next block starts immediately following the previous one - offset += block_size; - } + // otherwise, the next block starts immediately following the previous one + offset += block.get_fixed_size(is_structured); } return trace_data; } @@ -154,8 +141,8 @@ void ExecutionTrace_::add_ecc_op_wires_to_proving_key(Builder& builder, zip_view(proving_key.polynomials.get_ecc_op_wires(), proving_key.polynomials.get_wires())) { for (size_t i = 0; i < builder.blocks.ecc_op.size(); ++i) { size_t idx = i + op_wire_offset; - ecc_op_wire[idx] = wire[idx]; - ecc_op_selector[idx] = 1; // construct selector as the indicator on the ecc op block + ecc_op_wire.at(idx) = wire[idx]; + ecc_op_selector.at(idx) = 1; // construct selector as the indicator on the ecc op block } } } diff --git a/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.hpp b/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.hpp index 752ef633ebc..502ab6d2689 100644 --- a/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.hpp @@ -16,14 +16,11 @@ template class ExecutionTrace_ { public: static constexpr size_t NUM_WIRES = Builder::NUM_WIRES; - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1078): Since Keccak doesn't have knowledge of Poseidon2 - // gate yet, we ignore the two related selectors - static constexpr size_t NUM_USED_SELECTORS = - !HasKeccak ? Builder::Arithmetization::NUM_SELECTORS : Builder::Arithmetization::NUM_SELECTORS - 2; + static constexpr size_t NUM_SELECTORS = Builder::Arithmetization::NUM_SELECTORS; struct TraceData { std::array wires; - std::array selectors; + std::array selectors; // A vector of sets (vectors) of addresses into the wire polynomials whose values are copy constrained std::vector copy_cycles; uint32_t ram_rom_offset = 0; // offset of the RAM/ROM block in the execution trace @@ -48,10 +45,13 @@ template class ExecutionTrace_ { std::string wire_tag = "w_" + std::to_string(idx + 1) + "_lagrange"; proving_key.polynomial_store.put(wire_tag, wires[idx].share()); } - for (size_t idx = 0; idx < Builder::Arithmetization::NUM_SELECTORS; ++idx) { - selectors[idx] = Polynomial(proving_key.circuit_size); - std::string selector_tag = builder.selector_names[idx] + "_lagrange"; - proving_key.polynomial_store.put(selector_tag, selectors[idx].share()); + { + ZoneScopedN("selector initialization"); + for (size_t idx = 0; idx < Builder::Arithmetization::NUM_SELECTORS; ++idx) { + selectors[idx] = Polynomial(proving_key.circuit_size); + std::string selector_tag = builder.selector_names[idx] + "_lagrange"; + proving_key.polynomial_store.put(selector_tag, selectors[idx].share()); + } } } { diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index 98be3e69610..cc443d58fa6 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -93,10 +93,10 @@ namespace bb { */ class PrecomputedEntitiesBase { public: + bool operator==(const PrecomputedEntitiesBase& other) const = default; uint64_t circuit_size; uint64_t log_circuit_size; uint64_t num_public_inputs; - CircuitType circuit_type; // TODO(#392) }; /** @@ -158,6 +158,7 @@ class VerificationKey_ : public PrecomputedCommitments { AggregationObjectPubInputIndices recursive_proof_public_input_indices = {}; uint64_t pub_inputs_offset = 0; + bool operator==(const VerificationKey_&) const = default; VerificationKey_() = default; VerificationKey_(const size_t circuit_size, const size_t num_public_inputs) { @@ -173,32 +174,25 @@ class VerificationKey_ : public PrecomputedCommitments { */ std::vector to_field_elements() { + using namespace bb::field_conversion; + + auto serialize_to_field_buffer = [](const auto& input, std::vector& buffer) { + std::vector input_fields = convert_to_bn254_frs(input); + buffer.insert(buffer.end(), input_fields.begin(), input_fields.end()); + }; + std::vector elements; - std::vector circuit_size_elements = bb::field_conversion::convert_to_bn254_frs(this->circuit_size); - elements.insert(elements.end(), circuit_size_elements.begin(), circuit_size_elements.end()); - // do the same for the rest of the fields - std::vector num_public_inputs_elements = - bb::field_conversion::convert_to_bn254_frs(this->num_public_inputs); - elements.insert(elements.end(), num_public_inputs_elements.begin(), num_public_inputs_elements.end()); - std::vector pub_inputs_offset_elements = - bb::field_conversion::convert_to_bn254_frs(this->pub_inputs_offset); - elements.insert(elements.end(), pub_inputs_offset_elements.begin(), pub_inputs_offset_elements.end()); - - std::vector contains_recursive_proof_elements = - bb::field_conversion::convert_to_bn254_frs(this->contains_recursive_proof); - elements.insert( - elements.end(), contains_recursive_proof_elements.begin(), contains_recursive_proof_elements.end()); - - std::vector recursive_proof_public_input_indices_elements = - bb::field_conversion::convert_to_bn254_frs(this->recursive_proof_public_input_indices); - elements.insert(elements.end(), - recursive_proof_public_input_indices_elements.begin(), - recursive_proof_public_input_indices_elements.end()); - - for (Commitment& comm : this->get_all()) { - std::vector comm_elements = bb::field_conversion::convert_to_bn254_frs(comm); - elements.insert(elements.end(), comm_elements.begin(), comm_elements.end()); + + serialize_to_field_buffer(this->circuit_size, elements); + serialize_to_field_buffer(this->num_public_inputs, elements); + serialize_to_field_buffer(this->pub_inputs_offset, elements); + serialize_to_field_buffer(this->contains_recursive_proof, elements); + serialize_to_field_buffer(this->recursive_proof_public_input_indices, elements); + + for (Commitment& commitment : this->get_all()) { + serialize_to_field_buffer(commitment, elements); } + return elements; } @@ -375,9 +369,6 @@ concept IsHonkFlavor = IsAnyOf concept IsUltraFlavor = IsAnyOf; -template -concept HasKeccak = IsAnyOf; - template concept IsGoblinFlavor = IsAnyOf, diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.test.cpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.test.cpp index da3681c37ad..7f231880626 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.test.cpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.test.cpp @@ -19,7 +19,7 @@ TEST(Flavor, Getters) for (auto& id_poly : proving_key.polynomials.get_ids()) { typename Flavor::Polynomial new_poly(proving_key.circuit_size); for (size_t i = 0; i < proving_key.circuit_size; ++i) { - id_poly[i] = coset_idx * proving_key.circuit_size + i; + id_poly.at(i) = coset_idx * proving_key.circuit_size + i; } ++coset_idx; } @@ -49,8 +49,8 @@ TEST(Flavor, AllEntitiesSpecialMemberFunctions) using Polynomial = bb::Polynomial; PartiallyEvaluatedMultivariates polynomials_A; - auto random_poly = Polynomial(10); - for (auto& coeff : random_poly) { + Polynomial random_poly{ 10 }; + for (auto& coeff : random_poly.coeffs()) { coeff = FF::random_element(); } diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 55336db7f0b..18415c42637 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -6,7 +6,7 @@ #include "barretenberg/eccvm/eccvm_verifier.hpp" #include "barretenberg/goblin/mock_circuits.hpp" #include "barretenberg/goblin/types.hpp" -#include "barretenberg/plonk_honk_shared/instance_inspector.hpp" +#include "barretenberg/plonk_honk_shared/proving_key_inspector.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.hpp" #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index a7a77544b06..02e7eb836c2 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -132,7 +132,7 @@ class GoblinMockCircuits { std::array op_queue_commitments; size_t idx = 0; for (auto& entry : op_queue->get_aggregate_transcript()) { - op_queue_commitments[idx++] = commitment_key.commit(entry); + op_queue_commitments[idx++] = commitment_key.commit({ 0, entry }); } // Store the commitment data for use by the prover of the next circuit op_queue->set_commitment_data(op_queue_commitments); diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/logderivative_library.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/logderivative_library.hpp index 8b949458710..940c88c8c6d 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/logderivative_library.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/logderivative_library.hpp @@ -49,11 +49,12 @@ void compute_logderivative_inverse(Polynomials& polynomials, auto& relation_para Relation::template compute_write_term(row, relation_parameters); denominator *= denominator_term; }); - inverse_polynomial[i] = denominator; + inverse_polynomial.at(i) = denominator; }; - // todo might be inverting zero in field bleh bleh - FF::batch_invert(inverse_polynomial); + // Compute inverse polynomial I in place by inverting the product at each row + // Note: zeroes are ignored as they are not used anyway + FF::batch_invert(inverse_polynomial.coeffs()); } /** diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp index d830b8fa1a5..01693c4766a 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp @@ -46,15 +46,14 @@ template void compute_concatenated_polynomials(typename Flavor size_t i = index / concatenation_groups[0].size(); // Get the index of the original polynomial size_t j = index % concatenation_groups[0].size(); - auto my_group = concatenation_groups[i]; + auto& my_group = concatenation_groups[i]; auto& current_target = targets[i]; - auto starting_write_offset = current_target.begin(); - auto finishing_read_offset = my_group[j].begin(); - std::advance(starting_write_offset, j * MINI_CIRCUIT_SIZE); - std::advance(finishing_read_offset, MINI_CIRCUIT_SIZE); // Copy into appropriate position in the concatenated polynomial - std::copy(my_group[j].begin(), finishing_read_offset, starting_write_offset); + // We offset by start_index() as the first 0 is not physically represented for shiftable values + for (size_t k = current_target.start_index(); k < MINI_CIRCUIT_SIZE; k++) { + current_target.at(j * MINI_CIRCUIT_SIZE + k) = my_group[j][k]; + } }; parallel_for(concatenation_groups.size() * concatenation_groups[0].size(), ordering_function); } @@ -85,9 +84,6 @@ template void compute_translator_range_constraint_ordered_polynomials(typename Flavor::ProverPolynomials& polynomials, size_t mini_circuit_dyadic_size) { - - using FF = typename Flavor::FF; - // Get constants constexpr auto sort_step = Flavor::SORT_STEP; constexpr auto num_concatenated_wires = Flavor::NUM_CONCATENATED_WIRES; @@ -113,10 +109,10 @@ void compute_translator_range_constraint_ordered_polynomials(typename Flavor::Pr } std::vector> ordered_vectors_uint(num_concatenated_wires); - auto ordered_constraint_polynomials = std::vector{ &polynomials.ordered_range_constraints_0, - &polynomials.ordered_range_constraints_1, - &polynomials.ordered_range_constraints_2, - &polynomials.ordered_range_constraints_3 }; + RefArray ordered_constraint_polynomials{ polynomials.ordered_range_constraints_0, + polynomials.ordered_range_constraints_1, + polynomials.ordered_range_constraints_2, + polynomials.ordered_range_constraints_3 }; std::vector extra_denominator_uint(full_circuit_size); // Get information which polynomials need to be concatenated @@ -166,12 +162,8 @@ void compute_translator_range_constraint_ordered_polynomials(typename Flavor::Pr // 2. Comparison operators for finite fields are operating on internal form, so we'd have to convert them from // Montgomery std::sort(current_vector.begin(), current_vector.end()); - // Copy the values into the actual polynomial - std::transform(current_vector.cbegin(), - current_vector.cend(), - (*ordered_constraint_polynomials[i]).begin(), - [](uint32_t in) { return FF(in); }); + ordered_constraint_polynomials[i].copy_vector(current_vector); }; // Construct the first 4 polynomials @@ -191,11 +183,8 @@ void compute_translator_range_constraint_ordered_polynomials(typename Flavor::Pr std::sort(std::execution::par_unseq, extra_denominator_uint.begin(), extra_denominator.end()); #endif - // And copy it to the actual polynomial - std::transform(extra_denominator_uint.cbegin(), - extra_denominator_uint.cend(), - polynomials.ordered_range_constraints_4.begin(), - [](uint32_t in) { return FF(in); }); + // Copy the values into the actual polynomial + polynomials.ordered_range_constraints_4.copy_vector(extra_denominator_uint); } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/honk/utils/honk_key_gen.hpp b/barretenberg/cpp/src/barretenberg/honk/utils/honk_key_gen.hpp index be1e37b4218..8f6b6a0a26c 100644 --- a/barretenberg/cpp/src/barretenberg/honk/utils/honk_key_gen.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/utils/honk_key_gen.hpp @@ -79,6 +79,8 @@ inline void output_vk_sol_ultra_honk(std::ostream& os, print_g1(key->q_elliptic, "qElliptic"); print_g1(key->q_aux, "qAux"); print_g1(key->q_lookup, "qLookup"); + print_g1(key->q_poseidon2_external, "qPoseidon2External"); + print_g1(key->q_poseidon2_internal, "qPoseidon2Internal"); print_g1(key->sigma_1, "s1"); print_g1(key->sigma_2, "s2"); print_g1(key->sigma_3, "s3"); diff --git a/barretenberg/cpp/src/barretenberg/honk/utils/testing.hpp b/barretenberg/cpp/src/barretenberg/honk/utils/testing.hpp index 7b0de5d5677..43bf7d55532 100644 --- a/barretenberg/cpp/src/barretenberg/honk/utils/testing.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/utils/testing.hpp @@ -19,7 +19,7 @@ typename Flavor::ProverPolynomials get_sequential_prover_polynomials(const size_ size_t value_idx = starting_value; for (auto& polynomial : prover_polynomials.get_all()) { polynomial = Polynomial(circuit_size); - for (auto& value : polynomial) { + for (auto& value : polynomial.coeffs()) { value = FF(value_idx++); } } @@ -35,7 +35,7 @@ template typename Flavor::ProverPolynomials get_zero_prover_po size_t circuit_size = 1 << log_circuit_size; for (auto& polynomial : prover_polynomials.get_all()) { polynomial = Polynomial(circuit_size); - for (auto& value : polynomial) { + for (auto& value : polynomial.coeffs()) { value = FF(0); } } diff --git a/barretenberg/cpp/src/barretenberg/numeric/random/engine.cpp b/barretenberg/cpp/src/barretenberg/numeric/random/engine.cpp index 0c3604cb92a..8af63177345 100644 --- a/barretenberg/cpp/src/barretenberg/numeric/random/engine.cpp +++ b/barretenberg/cpp/src/barretenberg/numeric/random/engine.cpp @@ -131,9 +131,13 @@ RNG& get_debug_randomness(bool reset, std::uint_fast64_t seed) */ RNG& get_randomness() { - // return get_debug_randomness(); +#ifdef BBERG_DEBUG_LOG + // Use determinism for logging + return get_debug_randomness(); +#else static RandomEngine engine; return engine; +#endif } } // namespace bb::numeric diff --git a/barretenberg/cpp/src/barretenberg/plonk/work_queue/work_queue.cpp b/barretenberg/cpp/src/barretenberg/plonk/work_queue/work_queue.cpp index 63a9c7cd089..b479585660c 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/work_queue/work_queue.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk/work_queue/work_queue.cpp @@ -82,8 +82,10 @@ void work_queue::put_ifft_data(std::shared_ptr result, const size_t work_i for (const auto& item : work_item_queue) { if (item.work_type == WorkType::IFFT) { if (count == work_item_number) { - bb::polynomial wire(key->circuit_size); - memcpy(wire.data().get(), result.get(), key->circuit_size * sizeof(bb::fr)); + bb::LegacyPolynomial wire(key->circuit_size); + memcpy(static_cast(wire.data().get()), + static_cast(result.get()), + key->circuit_size * sizeof(bb::fr)); key->polynomial_store.put(item.tag, std::move(wire)); return; } diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp index 8f40ef2a8fd..ba90244a20d 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp @@ -87,7 +87,10 @@ template class ExecutionTr #endif } - uint32_t get_fixed_size() const { return fixed_size; } + uint32_t get_fixed_size(bool is_structured = true) const + { + return is_structured ? fixed_size : static_cast(size()); + } void set_fixed_size(uint32_t size_in) { fixed_size = size_in; } #ifdef TRACY_HACK_GATES_AS_MEMORY ~ExecutionTraceBlock() diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/max_block_size_tracker.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/max_block_size_tracker.hpp index b9d1f64f721..864d3f25944 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/max_block_size_tracker.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/max_block_size_tracker.hpp @@ -1,3 +1,5 @@ +#pragma once + #include "barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp" #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp index be4ca5b5fcb..52f5ff80a2f 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp @@ -30,8 +30,6 @@ template class UltraArith { aux, lookup, poseidon_external, poseidon_internal }; } - auto get_for_ultra_keccak() { return RefArray{ pub_inputs, arithmetic, delta_range, elliptic, aux, lookup }; } - bool operator==(const UltraTraceBlocks& other) const = default; }; @@ -125,12 +123,6 @@ template class UltraArith { this->aux, this->lookup, this->poseidon_external, this->poseidon_internal }; } - auto get_for_ultra_keccak() - { - return RefArray{ this->pub_inputs, this->arithmetic, this->delta_range, - this->elliptic, this->aux, this->lookup }; - } - void summarize() const { info("Gate blocks summary:"); diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp index 543f282fb05..35c2a5ec02a 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp @@ -29,10 +29,10 @@ void construct_lookup_table_polynomials(const RefArray (n+i) // These indices are chosen so they can easily be computed by the verifier. They can expect the running // product to be equal to the "public input delta" that is computed in - current_permutation_poly[i] = -FF(current_mapping.row_index + 1 + num_gates * current_mapping.column_index); + current_permutation_poly.at(i) = + -FF(current_mapping.row_index + 1 + num_gates * current_mapping.column_index); } else if (current_mapping.is_tag) { // Set evaluations to (arbitrary) values disjoint from non-tag values - current_permutation_poly[i] = num_gates * Flavor::NUM_WIRES + current_mapping.row_index; + current_permutation_poly.at(i) = num_gates * Flavor::NUM_WIRES + current_mapping.row_index; } else { // For the regular permutation we simply point to the next location by setting the evaluation to its // index - current_permutation_poly[i] = FF(current_mapping.row_index + num_gates * current_mapping.column_index); + current_permutation_poly.at(i) = FF(current_mapping.row_index + num_gates * current_mapping.column_index); } ITERATE_OVER_DOMAIN_END; wire_index++; diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/instance_inspector.cpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/instance_inspector.cpp deleted file mode 100644 index 529a3b46b02..00000000000 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/instance_inspector.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "instance_inspector.hpp" - -// Hack to make the module compile. \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index fd988bfd042..bf2859365d0 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -1,5 +1,6 @@ #pragma once #include "barretenberg/common/constexpr_utils.hpp" +#include "barretenberg/common/debug_log.hpp" #include "barretenberg/common/thread.hpp" #include "barretenberg/common/zip_view.hpp" #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" @@ -57,8 +58,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // Allocate numerator/denominator polynomials that will serve as scratch space // TODO(zac) we can re-use the permutation polynomial as the numerator polynomial. Reduces readability size_t circuit_size = full_polynomials.get_polynomial_size(); - Polynomial numerator{ circuit_size }; - Polynomial denominator{ circuit_size }; + Polynomial numerator{ circuit_size, circuit_size }; + Polynomial denominator{ circuit_size, circuit_size }; // Step (1) // Populate `numerator` and `denominator` with the algebra described by Relation @@ -74,13 +75,16 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, for (auto [eval, full_poly] : zip_view(evaluations.get_all(), full_polynomials.get_all())) { eval = full_poly.size() > i ? full_poly[i] : 0; } - numerator[i] = GrandProdRelation::template compute_grand_product_numerator( + numerator.at(i) = GrandProdRelation::template compute_grand_product_numerator( evaluations, relation_parameters); - denominator[i] = GrandProdRelation::template compute_grand_product_denominator( + denominator.at(i) = GrandProdRelation::template compute_grand_product_denominator( evaluations, relation_parameters); } }); + DEBUG_LOG_ALL(numerator.coeffs()); + DEBUG_LOG_ALL(denominator.coeffs()); + // Step (2) // Compute the accumulating product of the numerator and denominator terms. // This step is split into three parts for efficient multithreading: @@ -100,13 +104,16 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, const size_t start = thread_idx * block_size; const size_t end = (thread_idx + 1) * block_size; for (size_t i = start; i < end - 1; ++i) { - numerator[i + 1] *= numerator[i]; - denominator[i + 1] *= denominator[i]; + numerator.at(i + 1) *= numerator[i]; + denominator.at(i + 1) *= denominator[i]; } partial_numerators[thread_idx] = numerator[end - 1]; partial_denominators[thread_idx] = denominator[end - 1]; }); + DEBUG_LOG_ALL(partial_numerators); + DEBUG_LOG_ALL(partial_denominators); + parallel_for(num_threads, [&](size_t thread_idx) { const size_t start = thread_idx * block_size; const size_t end = (thread_idx + 1) * block_size; @@ -119,25 +126,31 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, denominator_scaling *= partial_denominators[j]; } for (size_t i = start; i < end; ++i) { - numerator[i] *= numerator_scaling; - denominator[i] *= denominator_scaling; + numerator.at(i) = numerator[i] * numerator_scaling; + denominator.at(i) = denominator[i] * denominator_scaling; } } // Final step: invert denominator - FF::batch_invert(std::span{ &denominator[start], block_size }); + FF::batch_invert(std::span{ &denominator.data()[start], block_size }); }); + DEBUG_LOG_ALL(numerator.coeffs()); + DEBUG_LOG_ALL(denominator.coeffs()); + // Step (3) Compute z_perm[i] = numerator[i] / denominator[i] auto& grand_product_polynomial = GrandProdRelation::get_grand_product_polynomial(full_polynomials); - grand_product_polynomial[0] = 0; + // We have a 'virtual' 0 at the start (as this is a to-be-shifted polynomial) + ASSERT(grand_product_polynomial.start_index() == 1); parallel_for(num_threads, [&](size_t thread_idx) { const size_t start = thread_idx * block_size; const size_t end = (thread_idx == num_threads - 1) ? circuit_size - 1 : (thread_idx + 1) * block_size; for (size_t i = start; i < end; ++i) { - grand_product_polynomial[i + 1] = numerator[i] * denominator[i]; + grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; } }); + + DEBUG_LOG_ALL(grand_product_polynomial.coeffs()); } /** diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/proving_key_inspector.cpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/proving_key_inspector.cpp new file mode 100644 index 00000000000..ca6a446e8bd --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/proving_key_inspector.cpp @@ -0,0 +1,3 @@ +#include "proving_key_inspector.hpp" + +// Hack to make the module compile. \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/instance_inspector.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/proving_key_inspector.hpp similarity index 100% rename from barretenberg/cpp/src/barretenberg/plonk_honk_shared/instance_inspector.hpp rename to barretenberg/cpp/src/barretenberg/plonk_honk_shared/proving_key_inspector.hpp diff --git a/barretenberg/cpp/src/barretenberg/polynomials/legacy_polynomial.hpp b/barretenberg/cpp/src/barretenberg/polynomials/legacy_polynomial.hpp index 28a5afe69ce..e709a7135af 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/legacy_polynomial.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/legacy_polynomial.hpp @@ -2,6 +2,8 @@ #include "barretenberg/common/mem.hpp" #include "barretenberg/crypto/sha256/sha256.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" +// for PolynomialSpan +#include "barretenberg/polynomials/polynomial.hpp" #include "evaluation_domain.hpp" #include "polynomial_arithmetic.hpp" #include @@ -105,17 +107,22 @@ template class LegacyPolynomial { Fr& operator[](const size_t i) { return coefficients_[i]; } + // For compatibility with Polynomial (which needs a special mutable accessor) Fr const& at(const size_t i) const { ASSERT(i < capacity()); return coefficients_[i]; - }; + } + // For compatibility with Polynomial (which needs a special mutable accessor) Fr& at(const size_t i) { ASSERT(i < capacity()); return coefficients_[i]; - }; + } + + // For compatibility with Polynomial (which needs a special safe mutation function) + void set_if_valid_index(size_t index, const Fr& value) { at(index) = value; } Fr evaluate(const Fr& z, size_t target_size) const; Fr evaluate(const Fr& z) const; @@ -151,6 +158,8 @@ template class LegacyPolynomial { bool is_empty() const { return size_ == 0; } + // For compatibility with polynomial.hpp + // void set(size_t i, const Fr& value) { (*this)[i] = value; }; /** * @brief Returns an std::span of the left-shift of self. * @@ -268,6 +277,20 @@ template class LegacyPolynomial { return p; } + /** + * @brief Implicit conversion operator to convert Polynomial to PolynomialSpan. + * NOTE: For LegacyPolynomial, unlike Polynomial, start index is always 0. + * @return PolynomialSpan A span covering the entire polynomial. + */ + operator PolynomialSpan() { return { 0, { coefficients_, coefficients_ + size() } }; } + + /** + * @brief Implicit conversion operator to convert Polynomial to PolynomialSpan. + * NOTE: For LegacyPolynomial, unlike Polynomial, start index is always 0. + * @return PolynomialSpan A span covering the entire polynomial. + */ + operator PolynomialSpan() const { return { 0, { coefficients_, coefficients_ + size() } }; } + private: // allocate a fresh memory pointer for backing memory // DOES NOT initialize memory diff --git a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp index 8280d141a66..9897f2d2173 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp @@ -3,6 +3,7 @@ #include "barretenberg/common/slab_allocator.hpp" #include "barretenberg/common/thread.hpp" #include "barretenberg/numeric/bitop/pow.hpp" +#include "barretenberg/polynomials/shared_shifted_virtual_zeroes_array.hpp" #include "polynomial_arithmetic.hpp" #include #include @@ -22,22 +23,36 @@ template std::shared_ptr _allocate_aligned_memory(size_t n_e return std::static_pointer_cast(get_mem_slab(sizeof(Fr) * n_elements)); } -template void Polynomial::allocate_backing_memory(size_t size, size_t virtual_size) +// Note: This function is pretty gnarly, but we try to make it the only function that deals +// with copying polynomials. It should be scrutinized thusly. +template +SharedShiftedVirtualZeroesArray _clone(const SharedShiftedVirtualZeroesArray& array, + size_t right_expansion = 0, + size_t left_expansion = 0) +{ + size_t expanded_size = array.size() + right_expansion + left_expansion; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) + std::shared_ptr backing_clone = _allocate_aligned_memory(expanded_size); + // zero any left extensions to the array + memset(static_cast(backing_clone.get()), 0, sizeof(Fr) * left_expansion); + // copy our cloned array over + memcpy(static_cast(backing_clone.get() + left_expansion), + static_cast(array.backing_memory_.get()), + sizeof(Fr) * array.size()); + // zero any right extensions to the array + memset(static_cast(backing_clone.get() + left_expansion + array.size()), 0, sizeof(Fr) * right_expansion); + return { array.start_ - left_expansion, array.end_ + right_expansion, array.virtual_size_, backing_clone }; +} + +template +void Polynomial::allocate_backing_memory(size_t size, size_t virtual_size, size_t start_index) { coefficients_ = SharedShiftedVirtualZeroesArray{ - size, /* actual memory size */ - virtual_size, /* virtual size, i.e. until what size do we conceptually have zeroes */ - 0, /* shift, initially 0 */ - _allocate_aligned_memory(size + MAXIMUM_COEFFICIENT_SHIFT) - /* Our backing memory, since shift is 0 it is equal to our memory size. - * We add one to the size here to allow for an efficient shift by 1 that retains size. */ + start_index, /* start index, used for shifted polynomials and offset 'islands' of non-zeroes */ + size + start_index, /* end index, actual memory used is (end - start) */ + virtual_size, /* virtual size, i.e. until what size do we conceptually have zeroes */ + _allocate_aligned_memory(size) }; - // We need to zero the extra padding memory that we reserve for shifts. - // We do this here as generally code that does not zero memory and then - // later initializes it won't generally also initialize the padding. - for (size_t i = 0; i < MAXIMUM_COEFFICIENT_SHIFT; i++) { - data()[size + i] = Fr{}; - } } /** @@ -49,10 +64,10 @@ template void Polynomial::allocate_backing_memory(size_t size, * * @param size The size of the polynomial. */ -template Polynomial::Polynomial(size_t size, size_t virtual_size) +template Polynomial::Polynomial(size_t size, size_t virtual_size, size_t start_index) { - allocate_backing_memory(size, virtual_size); - memset(static_cast(coefficients_.data()), 0, sizeof(Fr) * size); + allocate_backing_memory(size, virtual_size, start_index); + memset(static_cast(coefficients_.backing_memory_.get()), 0, sizeof(Fr) * size); } /** @@ -62,11 +77,10 @@ template Polynomial::Polynomial(size_t size, size_t virtual_si * @param size The initial size of the polynomial. * @param flag Signals that we do not zero memory. */ -template Polynomial::Polynomial(size_t size, size_t virtual_size, DontZeroMemory flag) +template +Polynomial::Polynomial(size_t size, size_t virtual_size, size_t start_index, [[maybe_unused]] DontZeroMemory flag) { - // Flag is unused, but we don't memset 0 if passed. - (void)flag; - allocate_backing_memory(size, virtual_size); + allocate_backing_memory(size, virtual_size, start_index); } template @@ -77,12 +91,8 @@ Polynomial::Polynomial(const Polynomial& other) // fully copying "expensive" constructor template Polynomial::Polynomial(const Polynomial& other, const size_t target_size) { - allocate_backing_memory(std::max(target_size, other.size()), other.virtual_size()); - - memcpy(static_cast(coefficients_.data()), - static_cast(other.coefficients_.data()), - sizeof(Fr) * other.size()); - zero_memory_beyond(other.size()); + ASSERT(other.size() <= target_size); + coefficients_ = _clone(other.coefficients_, target_size - other.size()); } // interpolation constructor @@ -92,15 +102,15 @@ Polynomial::Polynomial(std::span interpolation_points, size_t virtual_size) : Polynomial(interpolation_points.size(), virtual_size) { - ASSERT(coefficients_.size_ > 0); + ASSERT(coefficients_.size() > 0); polynomial_arithmetic::compute_efficient_interpolation( - evaluations.data(), coefficients_.data(), interpolation_points.data(), coefficients_.size_); + evaluations.data(), coefficients_.data(), interpolation_points.data(), coefficients_.size()); } template Polynomial::Polynomial(std::span coefficients, size_t virtual_size) { - allocate_backing_memory(coefficients.size(), virtual_size); + allocate_backing_memory(coefficients.size(), virtual_size, 0); memcpy(static_cast(data()), static_cast(coefficients.data()), sizeof(Fr) * coefficients.size()); } @@ -113,10 +123,7 @@ template Polynomial& Polynomial::operator=(const Polynomia if (this == &other) { return *this; } - allocate_backing_memory(other.coefficients_.size_, other.coefficients_.virtual_size_); - memcpy(static_cast(coefficients_.data()), - static_cast(other.coefficients_.data()), - sizeof(Fr) * other.coefficients_.size_); + coefficients_ = _clone(other.coefficients_); return *this; } @@ -138,7 +145,9 @@ template bool Polynomial::operator==(Polynomial const& rhs) co return false; } // Each coefficient must agree - for (size_t i = 0; i < std::max(size(), rhs.size()); i++) { + for (size_t i = std::min(coefficients_.start_, rhs.coefficients_.start_); + i < std::max(coefficients_.end_, rhs.coefficients_.end_); + i++) { if (coefficients_.get(i) != rhs.coefficients_.get(i)) { return false; } @@ -146,22 +155,21 @@ template bool Polynomial::operator==(Polynomial const& rhs) co return true; } -template Polynomial& Polynomial::operator+=(std::span other) +template Polynomial& Polynomial::operator+=(PolynomialSpan other) { - const size_t other_size = other.size(); - ASSERT(in_place_operation_viable(other_size)); - - size_t num_threads = calculate_num_threads(other_size); - size_t range_per_thread = other_size / num_threads; - size_t leftovers = other_size - (range_per_thread * num_threads); + // Compute the subset that is defined in both polynomials + ASSERT(start_index() <= other.start_index); + ASSERT(end_index() >= other.end_index()); + size_t num_threads = calculate_num_threads(other.size()); + size_t range_per_thread = other.size() / num_threads; + size_t leftovers = other.size() - (range_per_thread * num_threads); parallel_for(num_threads, [&](size_t j) { - size_t offset = j * range_per_thread; + size_t offset = j * range_per_thread + other.start_index; size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread; for (size_t i = offset; i < end; ++i) { - coefficients_.data()[i] += other[i]; + at(i) += other[i]; } }); - return *this; } @@ -179,8 +187,8 @@ template Fr Polynomial::evaluate_mle(std::span evalu { const size_t m = evaluation_points.size(); - // To simplify handling of edge cases, we assume that size_ is always a power of 2 - ASSERT(size() == static_cast(1 << m)); + // To simplify handling of edge cases, we assume that the index space is always a power of 2 + ASSERT(virtual_size() == static_cast(1 << m)); // we do m rounds l = 0,...,m-1. // in round l, n_l is the size of the buffer containing the Polynomial partially evaluated @@ -189,27 +197,30 @@ template Fr Polynomial::evaluate_mle(std::span evalu size_t n_l = 1 << (m - 1); // temporary buffer of half the size of the Polynomial - // TODO(AD): Make this a Polynomial with DontZeroMemory::FLAG + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1096): Make this a Polynomial with DontZeroMemory::FLAG auto tmp_ptr = _allocate_aligned_memory(sizeof(Fr) * n_l); auto tmp = tmp_ptr.get(); - const Fr* prev = data(); + size_t offset = 0; if (shift) { - ASSERT(prev[0] == Fr::zero()); - prev++; + ASSERT((*this)[0] == Fr::zero()); + offset++; } Fr u_l = evaluation_points[0]; for (size_t i = 0; i < n_l; ++i) { - // curr[i] = (Fr(1) - u_l) * prev[i << 1] + u_l * prev[(i << 1) + 1]; - tmp[i] = prev[i << 1] + u_l * (prev[(i << 1) + 1] - prev[i << 1]); + // curr[i] = (Fr(1) - u_l) * prev[i * 2] + u_l * prev[(i * 2) + 1]; + // Note: i * 2 + 1 + offset might equal virtual_size. This used to subtlely be handled by extra capacity padding + // (and there used to be no assert time checks, which this constant helps with). + const size_t ALLOW_ONE_PAST_READ = 1; + tmp[i] = get(i * 2 + offset) + u_l * (get(i * 2 + 1 + offset, ALLOW_ONE_PAST_READ) - get(i * 2 + offset)); } // partially evaluate the m-1 remaining points for (size_t l = 1; l < m; ++l) { n_l = 1 << (m - l - 1); u_l = evaluation_points[l]; for (size_t i = 0; i < n_l; ++i) { - tmp[i] = tmp[i << 1] + u_l * (tmp[(i << 1) + 1] - tmp[i << 1]); + tmp[i] = tmp[i * 2] + u_l * (tmp[(i * 2) + 1] - tmp[i * 2]); } } Fr result = tmp[0]; @@ -239,21 +250,21 @@ template Polynomial Polynomial::partial_evaluate_mle(std:: for (size_t i = 0; i < n_l; i++) { // Initiate our intermediate results using this Polynomial. - intermediate[i] = get(i) + u_l * (get(i + n_l) - get(i)); + intermediate.at(i) = get(i) + u_l * (get(i + n_l) - get(i)); } // Evaluate m-1 variables X_{n-l-1}, ..., X_{n-2} at m-1 remaining values u_0,...,u_{m-2}) for (size_t l = 1; l < m; ++l) { n_l = 1 << (n - l - 1); u_l = evaluation_points[m - l - 1]; for (size_t i = 0; i < n_l; ++i) { - intermediate[i] += u_l * (intermediate[i + n_l] - intermediate[i]); + intermediate.at(i) = intermediate[i] + u_l * (intermediate[i + n_l] - intermediate[i]); } } // Construct resulting Polynomial g(X_0,…,X_{n-m-1})) = p(X_0,…,X_{n-m-1},u_0,...u_{m-1}) from buffer Polynomial result(n_l, n_l, DontZeroMemory::FLAG); for (size_t idx = 0; idx < n_l; ++idx) { - result[idx] = intermediate[idx]; + result.at(idx) = intermediate[idx]; } return result; @@ -273,29 +284,26 @@ Fr Polynomial::compute_barycentric_evaluation(const Fr& z, const EvaluationD return polynomial_arithmetic::compute_barycentric_evaluation(data(), domain.size, z, domain); } -template Polynomial& Polynomial::operator-=(std::span other) +template Polynomial& Polynomial::operator-=(PolynomialSpan other) { - const size_t other_size = other.size(); - ASSERT(in_place_operation_viable(other_size)); - - size_t num_threads = calculate_num_threads(other_size); - size_t range_per_thread = other_size / num_threads; - size_t leftovers = other_size - (range_per_thread * num_threads); + // Compute the subset that is defined in both polynomials + ASSERT(start_index() <= other.start_index); + ASSERT(end_index() >= other.end_index()); + size_t num_threads = calculate_num_threads(other.size()); + size_t range_per_thread = other.size() / num_threads; + size_t leftovers = other.size() - (range_per_thread * num_threads); parallel_for(num_threads, [&](size_t j) { - size_t offset = j * range_per_thread; + size_t offset = j * range_per_thread + other.start_index; size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread; for (size_t i = offset; i < end; ++i) { - coefficients_.data()[i] -= other[i]; + at(i) -= other[i]; } }); - return *this; } template Polynomial& Polynomial::operator*=(const Fr scaling_factor) { - ASSERT(in_place_operation_viable()); - size_t num_threads = calculate_num_threads(size()); size_t range_per_thread = size() / num_threads; size_t leftovers = size() - (range_per_thread * num_threads); @@ -303,64 +311,47 @@ template Polynomial& Polynomial::operator*=(const Fr scali size_t offset = j * range_per_thread; size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread; for (size_t i = offset; i < end; ++i) { - coefficients_.data()[i] *= scaling_factor; + data()[i] *= scaling_factor; } }); return *this; } -template void Polynomial::add_scaled(std::span other, Fr scaling_factor) +template Polynomial Polynomial::full() const { - const size_t other_size = other.size(); - ASSERT(in_place_operation_viable(other_size)); - - size_t num_threads = calculate_num_threads(other_size); - size_t range_per_thread = other_size / num_threads; - size_t leftovers = other_size - (range_per_thread * num_threads); + Polynomial result = *this; + // Make 0..virtual_size usable + result.coefficients_ = _clone(coefficients_, virtual_size() - end_index(), start_index()); + return result; +} +template void Polynomial::add_scaled(PolynomialSpan other, Fr scaling_factor) & +{ + // Compute the subset that is defined in both polynomials + ASSERT(start_index() <= other.start_index); + ASSERT(end_index() >= other.end_index()); + size_t num_threads = calculate_num_threads(other.size()); + size_t range_per_thread = other.size() / num_threads; + size_t leftovers = other.size() - (range_per_thread * num_threads); parallel_for(num_threads, [&](size_t j) { - size_t offset = j * range_per_thread; + size_t offset = j * range_per_thread + other.start_index; size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread; for (size_t i = offset; i < end; ++i) { - data()[i] += scaling_factor * other[i]; + at(i) += scaling_factor * other[i]; } }); } -/** - * @brief Returns a Polynomial the left-shift of self. - * - * @details If the n coefficients of self are (0, a₁, …, aₙ₋₁), - * we returns the view of the n-1 coefficients (a₁, …, aₙ₋₁). - */ template Polynomial Polynomial::shifted() const { - ASSERT(data()[0].is_zero()); - ASSERT(size() > 0); - ASSERT(data()[size()].is_zero()); // relies on MAXIMUM_COEFFICIENT_SHIFT >= 1 + ASSERT(coefficients_.start_ >= 1); Polynomial result; result.coefficients_ = coefficients_; - result.coefficients_.shift_ += 1; - // We only expect to shift by MAXIMUM_COEFFICIENT_SHIFT - ASSERT(result.coefficients_.shift_ <= MAXIMUM_COEFFICIENT_SHIFT); + result.coefficients_.start_ -= 1; + result.coefficients_.end_ -= 1; return result; } -/** - * @brief sets a block of memory to all zeroes - * Used, for example, when one Polynomioal is instantiated from another one with size_>= other.size_. - */ -template void Polynomial::zero_memory_beyond(const size_t start_position) -{ - size_t end = size(); - ASSERT(end >= start_position); - - size_t delta = end - start_position; - if (delta > 0) { - memset(static_cast(&data()[start_position]), 0, sizeof(Fr) * delta); - } -} - template class Polynomial; template class Polynomial; diff --git a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp index 7840699dc65..fa6608456c5 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp @@ -1,19 +1,36 @@ #pragma once #include "barretenberg/common/mem.hpp" +#include "barretenberg/common/zip_view.hpp" #include "barretenberg/crypto/sha256/sha256.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" #include "barretenberg/polynomials/shared_shifted_virtual_zeroes_array.hpp" #include "evaluation_domain.hpp" #include "polynomial_arithmetic.hpp" +#include #include +#include namespace bb { +/* Span class with a start index offset. + * We conceptually have a span like a_0 + a_1 x ... a_n x^n and then multiply by x^start_index. + * This allows more efficient representation than a fully defined span for 'islands' of zeroes. */ +template struct PolynomialSpan { + size_t start_index; + std::span span; + size_t end_index() const { return start_index + size(); } + Fr* data() { return span.data(); } + size_t size() const { return span.size(); } + Fr& operator[](size_t index) { return span[index - start_index]; } + const Fr& operator[](size_t index) const { return span[index - start_index]; } +}; + /** - * @brief Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x + a_n x^n of + * @brief Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x ... a_n x^n of * a finite field polynomial equation of degree that is at most the size of some zk circuit. * Past 'n' it has a virtual size where it conceptually has coefficients all equal to 0. * Notably, we allow indexing past 'n' up to our virtual size (checked only in a debug build, however). + * As well, we have a start index that means coefficients before start_index are also considered to be 0. * The polynomial is used to represent the gates of our arithmetized zk programs. * Polynomials use the majority of the memory in proving, so caution should be used in making sure * unnecessary copies are avoided, both for avoiding unnecessary memory usage and performance @@ -28,13 +45,19 @@ template class Polynomial { using FF = Fr; enum class DontZeroMemory { FLAG }; - Polynomial(size_t size, size_t virtual_size); + Polynomial(size_t size, size_t virtual_size, size_t start_index = 0); // Intended just for plonk, where size == virtual_size always Polynomial(size_t size) : Polynomial(size, size) {} // Constructor that does not initialize values, use with caution to save time. - Polynomial(size_t size, size_t virtual_size, DontZeroMemory flag); + Polynomial(size_t size, size_t virtual_size, size_t start_index, DontZeroMemory flag); + Polynomial(size_t size, size_t virtual_size, DontZeroMemory flag) + : Polynomial(size, virtual_size, 0, flag) + {} + Polynomial(size_t size, DontZeroMemory flag) + : Polynomial(size, size, flag) + {} Polynomial(const Polynomial& other); Polynomial(const Polynomial& other, size_t target_size); @@ -46,6 +69,10 @@ template class Polynomial { : Polynomial(coefficients, coefficients.size()) {} + static Polynomial shiftable(size_t virtual_size) + { + return Polynomial(/*actual size*/ virtual_size - 1, virtual_size, /*shiftable offset*/ 1); + } // Allow polynomials to be entirely reset/dormant Polynomial() = default; @@ -90,15 +117,16 @@ template class Polynomial { bool operator==(Polynomial const& rhs) const; - void set(size_t i, const Fr& value) { coefficients_.set(i, value); }; - Fr get(size_t i) const { return coefficients_.get(i); }; - - bool is_empty() const { return coefficients_.size_ == 0; } + /** + * @brief Retrieves the value at the specified index. + * + * @param index The index from which to retrieve the value. + * @param virtual_padding For the rare case where we explicitly want the 0-returning behavior beyond our usual + * virtual_size. + */ + const Fr& get(size_t i, size_t virtual_padding = 0) const { return coefficients_.get(i, virtual_padding); }; - Fr* begin() { return data(); } - Fr* end() { return data() + size(); } - const Fr* begin() const { return data(); } - const Fr* end() const { return data() + size(); } + bool is_empty() const { return coefficients_.size() == 0; } /** * @brief Returns a Polynomial the left-shift of self. @@ -145,17 +173,16 @@ template class Polynomial { requires polynomial_arithmetic::SupportsFFT; /** - * @brief Divides p(X) by (X-r₁)⋯(X−rₘ) in-place. + * @brief Divides p(X) by (X-r) in-place. * Assumes that p(rⱼ)=0 for all j * * @details we specialize the method when only a single root is given. * if one of the roots is 0, then we first factor all other roots. * dividing by X requires only a left shift of all coefficient. * - * @param roots list of roots (r₁,…,rₘ) + * @param root a single root r */ - void factor_roots(std::span roots) { polynomial_arithmetic::factor_roots(std::span{ *this }, roots); }; - void factor_roots(const Fr& root) { polynomial_arithmetic::factor_roots(std::span{ *this }, root); }; + void factor_roots(const Fr& root) { polynomial_arithmetic::factor_roots(coeffs(), root); }; Fr evaluate(const Fr& z, size_t target_size) const; Fr evaluate(const Fr& z) const; @@ -166,21 +193,21 @@ template class Polynomial { * @param other q(X) * @param scaling_factor scaling factor by which all coefficients of q(X) are multiplied */ - void add_scaled(std::span other, Fr scaling_factor); + void add_scaled(PolynomialSpan other, Fr scaling_factor) &; /** * @brief adds the polynomial q(X) 'other'. * * @param other q(X) */ - Polynomial& operator+=(std::span other); + Polynomial& operator+=(PolynomialSpan other); /** * @brief subtracts the polynomial q(X) 'other'. * * @param other q(X) */ - Polynomial& operator-=(std::span other); + Polynomial& operator-=(PolynomialSpan other); /** * @brief sets this = p(X) to s⋅p(X) @@ -189,42 +216,125 @@ template class Polynomial { */ Polynomial& operator*=(Fr scaling_factor); - std::span as_span() const { return { coefficients_.data(), coefficients_.data() + coefficients_.size_ }; } - std::span as_span() { return { coefficients_.data(), coefficients_.data() + coefficients_.size_ }; } - std::size_t size() const { return coefficients_.size_; } - std::size_t virtual_size() const { return coefficients_.virtual_size_; } + std::size_t size() const { return coefficients_.size(); } + std::size_t virtual_size() const { return coefficients_.virtual_size(); } Fr* data() { return coefficients_.data(); } const Fr* data() const { return coefficients_.data(); } - Fr& operator[](size_t i) + + /** + * @brief Our mutable accessor, unlike operator[]. + * We abuse precedent a bit to differentiate at() and operator[] as mutable and immutable, respectively. + * This means at() can only index within start_index()..end_index() unlike operator[] which can index + * 0..virtual_size + * @param index the index, to be subtracted by start_index() and read into the array memory + * @return Fr& a mutable reference. + */ + Fr& at(size_t index) { return coefficients_[index]; } + const Fr& at(size_t index) const { return coefficients_[index]; } + + const Fr& operator[](size_t i) { return get(i); } + const Fr& operator[](size_t i) const { return get(i); } + + static Polynomial random(size_t size, size_t start_index = 0) { - ASSERT(i < size()); - return coefficients_.data()[i]; + return random(size - start_index, size, start_index); } - const Fr& operator[](size_t i) const + + static Polynomial random(size_t size, size_t virtual_size, size_t start_index) { - ASSERT(i < size()); - return coefficients_.data()[i]; + Polynomial p(size, virtual_size, start_index, DontZeroMemory::FLAG); + std::generate_n(p.coefficients_.data(), size, []() { return Fr::random_element(); }); + return p; } - static Polynomial random(size_t size) { return random(size, size); } + /** + * @brief Copys the polynomial, but with the whole address space usable. + * The value of the polynomial remains the same, but defined memory region differs. + * + * @return a polynomial with a larger size() but same virtual_size() + */ + Polynomial full() const; - static Polynomial random(size_t size, size_t virtual_size) + // The extents of the actual memory-backed polynomial region + size_t start_index() const { return coefficients_.start_; } + size_t end_index() const { return coefficients_.end_; } + + /** + * @brief Strictly iterates the defined region of the polynomial. + * We keep this explicit, instead of having an implicit conversion to span. + * This is safer as it is more likely that we need to consider our start_index() + * along with the span, as in PolynomialSpan below. + * + * @return std::span a span covering start_index() to end_index() + */ + std::span coeffs(size_t offset = 0) { return { data() + offset, data() + size() }; } + std::span coeffs(size_t offset = 0) const { return { data() + offset, data() + size() }; } + /** + * @brief Convert to an std::span bundled with our start index. + * @return PolynomialSpan A span covering the entire polynomial. + */ + operator PolynomialSpan() { return { start_index(), coeffs() }; } + + /** + * @brief Convert to an std::span bundled with our start index. + * @return PolynomialSpan A span covering the entire polynomial. + */ + operator PolynomialSpan() const { return { start_index(), coeffs() }; } + + auto indices() const { return std::ranges::iota_view(start_index(), end_index()); } + auto indexed_values() { return zip_view(indices(), coeffs()); } + auto indexed_values() const { return zip_view(indices(), coeffs()); } + /** + * @brief Is this index valid for a set? i.e. calling poly.at(index) = value + */ + bool is_valid_set_index(size_t index) const { return (index >= start_index() && index < end_index()); } + /** + * @brief Like setting with at(), but allows zeroes to result in no set. + */ + void set_if_valid_index(size_t index, const Fr& value) { - Polynomial p(size, virtual_size, DontZeroMemory::FLAG); - std::generate_n(p.coefficients_.data(), size, []() { return Fr::random_element(); }); - return p; + ASSERT(value.is_zero() || is_valid_set_index(index)); + if (is_valid_set_index(index)) { + at(index) = value; + } + } + + /** + * @brief Copy over values from a vector that is of a convertible type. + * + * @tparam T a convertible type + * @param vec the vector + */ + template void copy_vector(const std::vector& vec) + { + ASSERT(vec.size() <= end_index()); + for (size_t i : indices()) { + ASSERT(i < vec.size()); + at(i) = vec[i]; + } + } + + /* + * @brief For quick and dirty comparisons. ONLY for development and log use! + */ + Fr debug_hash() const + { + Fr result{ 0 }; + for (size_t i = start_index(); i < end_index(); i++) { + result += (*this)[i] * i; + } + return result; } private: // allocate a fresh memory pointer for backing memory // DOES NOT initialize memory - void allocate_backing_memory(size_t size, size_t virtual_size); + void allocate_backing_memory(size_t size, size_t virtual_size, size_t start_index); // safety check for in place operations - bool in_place_operation_viable(size_t domain_size = 0) { return (size() >= domain_size); } + bool in_place_operation_viable(size_t domain_size) { return (size() >= domain_size); } - void zero_memory_beyond(size_t start_position); // When a polynomial is instantiated from a size alone, the memory allocated corresponds to // input size + MAXIMUM_COEFFICIENT_SHIFT to support 'shifted' coefficients efficiently. const static size_t MAXIMUM_COEFFICIENT_SHIFT = 1; @@ -251,4 +361,12 @@ template inline std::ostream& operator<<(std::ostream& os, Polynom << "]"; } +template auto zip_polys(Poly&& poly, Polys&&... polys) +{ + // Ensure all polys have the same start_index() and end_index() as poly + // Use fold expression to check all polys exactly match our size + ASSERT((poly.start_index() == polys.start_index() && poly.end_index() == polys.end_index()) && ...); + return zip_view(poly.indices(), poly.coeffs(), polys.coeffs()...); +} + } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.test.cpp b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.test.cpp index f7c67ff708b..c7fdc8bd454 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/polynomial.test.cpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/polynomial.test.cpp @@ -9,8 +9,7 @@ TEST(Polynomial, Shifted) using FF = bb::fr; using Polynomial = bb::Polynomial; const size_t SIZE = 10; - auto poly = Polynomial::random(SIZE); - poly[0] = 0; // make it shiftable + auto poly = Polynomial::random(SIZE, /*shiftable*/ 1); // Instantiate the shift via the shited method auto poly_shifted = poly.shifted(); @@ -23,7 +22,7 @@ TEST(Polynomial, Shifted) } // If I change the original polynomial, the shift is updated accordingly - poly[3] = 25; + poly.at(3) = 25; for (size_t i = 0; i < poly_shifted.size() - 1; ++i) { EXPECT_EQ(poly_shifted.get(i), poly.get(i + 1)); } @@ -44,10 +43,10 @@ TEST(Polynomial, Share) EXPECT_EQ(poly_clone, poly); // Changing one changes the other - poly[3] = 25; + poly.at(3) = 25; EXPECT_EQ(poly_clone, poly); - poly_clone[2] = 13; + poly_clone.at(2) = 13; EXPECT_EQ(poly_clone, poly); // If reset the original poly, it will no longer be equal to the clone made earlier @@ -57,3 +56,111 @@ TEST(Polynomial, Share) EXPECT_NE(poly_clone, poly); } + +// Simple test/demonstration of various edge conditions +TEST(Polynomial, Indices) +{ + auto poly = bb::Polynomial::random(100, /*offset*/ 1); + EXPECT_EQ(poly.start_index(), 1); + EXPECT_EQ((*poly.indices().begin()), poly.start_index()); + EXPECT_EQ(std::get<0>(*poly.indexed_values().begin()), poly.start_index()); + EXPECT_EQ(std::get<1>(*poly.indexed_values().begin()), poly[poly.start_index()]); +} + +#ifndef NDEBUG +// Only run in an assert-enabled test suite. +TEST(Polynomial, AddScaledEdgeConditions) +{ + // Suppress warnings about fork(), we're OK with the edge cases. + GTEST_FLAG_SET(death_test_style, "threadsafe"); + using FF = bb::fr; + auto test_subset_good = []() { + // Contained within poly + auto poly = bb::Polynomial::random(4, /*start index*/ 0); + poly.add_scaled(bb::Polynomial::random(4, /*start index*/ 1), 1); + }; + ASSERT_NO_FATAL_FAILURE(test_subset_good()); + auto test_subset_bad1 = []() { + // Not contained within poly + auto poly = bb::Polynomial::random(4, /*start index*/ 1); + poly.add_scaled(bb::Polynomial::random(4, /*start index*/ 0), 1); + }; + ASSERT_DEATH(test_subset_bad1(), ".*start_index.*other.start_index.*"); + auto test_subset_bad2 = []() { + // Not contained within poly + auto poly = bb::Polynomial::random(4, /*start index*/ 0); + poly.add_scaled(bb::Polynomial::random(5, /*start index*/ 0), 1); + }; + ASSERT_DEATH(test_subset_bad2(), ".*end_index.*other.end_index.*"); +} + +TEST(Polynomial, OperatorAddEdgeConditions) +{ + // Suppress warnings about fork(), we're OK with the edge cases. + GTEST_FLAG_SET(death_test_style, "threadsafe"); + using FF = bb::fr; + auto test_subset_good = []() { + // Contained within poly + auto poly = bb::Polynomial::random(4, /*start index*/ 0); + poly += bb::Polynomial::random(4, /*start index*/ 1); + }; + ASSERT_NO_FATAL_FAILURE(test_subset_good()); + auto test_subset_bad1 = []() { + // Not contained within poly + auto poly = bb::Polynomial::random(4, /*start index*/ 1); + poly += bb::Polynomial::random(4, /*start index*/ 0); + }; + ASSERT_DEATH(test_subset_bad1(), ".*start_index.*other.start_index.*"); + auto test_subset_bad2 = []() { + // Not contained within poly + auto poly = bb::Polynomial::random(4, /*start index*/ 0); + poly += bb::Polynomial::random(5, /*start index*/ 0); + }; + ASSERT_DEATH(test_subset_bad2(), ".*end_index.*other.end_index.*"); +} + +TEST(Polynomial, OperatorSubtractEdgeConditions) +{ + // Suppress warnings about fork(), we're OK with the edge cases. + GTEST_FLAG_SET(death_test_style, "threadsafe"); + using FF = bb::fr; + auto test_subset_good = []() { + // Contained within poly + auto poly = bb::Polynomial::random(4, /*start index*/ 0); + poly -= bb::Polynomial::random(4, /*start index*/ 1); + }; + ASSERT_NO_FATAL_FAILURE(test_subset_good()); + auto test_subset_bad1 = []() { + // Not contained within poly + auto poly = bb::Polynomial::random(4, /*start index*/ 1); + poly -= bb::Polynomial::random(4, /*start index*/ 0); + }; + ASSERT_DEATH(test_subset_bad1(), ".*start_index.*other.start_index.*"); + auto test_subset_bad2 = []() { + // Not contained within poly + auto poly = bb::Polynomial::random(4, /*start index*/ 0); + poly -= bb::Polynomial::random(5, /*start index*/ 0); + }; + ASSERT_DEATH(test_subset_bad2(), ".*end_index.*other.end_index.*"); +} + +// Makes a vector fully of the virtual_size aka degree + 1 +TEST(Polynomial, Full) +{ + // Suppress warnings about fork(), we're OK with the edge cases. + GTEST_FLAG_SET(death_test_style, "threadsafe"); + using FF = bb::fr; + size_t degree_plus_1 = 10; + auto full_good = [=]() { + auto poly = bb::Polynomial::random(1, degree_plus_1, /*start index*/ degree_plus_1 - 1); + poly = poly.full(); + poly -= bb::Polynomial::random(degree_plus_1, /*start index*/ 0); + }; + ASSERT_NO_FATAL_FAILURE(full_good()); + auto no_full_bad = [=]() { + auto poly = bb::Polynomial::random(1, degree_plus_1, /*start index*/ degree_plus_1 - 1); + poly -= bb::Polynomial::random(degree_plus_1, /*start index*/ 0); + }; + ASSERT_DEATH(no_full_bad(), ".*start_index.*other.start_index.*"); +} +#endif \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/polynomials/polynomial_arithmetic.hpp b/barretenberg/cpp/src/barretenberg/polynomials/polynomial_arithmetic.hpp index 4de39d5a918..797a811b0e6 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/polynomial_arithmetic.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/polynomial_arithmetic.hpp @@ -269,7 +269,7 @@ template void factor_roots(std::span polynomial, std::span inline void read(B& buf, polynomial& p) { - uint32_t size; + uint32_t size = 0; serialize::read(buf, size); p = polynomial(size); - memcpy(&p[0], buf, size * sizeof(fr)); + memcpy(static_cast(&p[0]), static_cast(buf), size * sizeof(fr)); if (!is_little_endian()) { for (size_t i = 0; i < size; ++i) { diff --git a/barretenberg/cpp/src/barretenberg/polynomials/shared_shifted_virtual_zeroes_array.hpp b/barretenberg/cpp/src/barretenberg/polynomials/shared_shifted_virtual_zeroes_array.hpp index acc99519e00..7dd50a99c96 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/shared_shifted_virtual_zeroes_array.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/shared_shifted_virtual_zeroes_array.hpp @@ -4,49 +4,115 @@ #include #include -// Shared pointer array of a type (in our case, a field) that is -// conceptually filled with 0's until 'virtual_size_', but with actual memory usage -// proportional to 'size'. -// As well, there is a 'shift_' member that can be used when we want to share the underlying array. -// Everything is public as this is intended to be wrapped by another class, namely Polynomial -// The name is a mouthful, but again as an internal bundling of details it is intended to be wrapped by -// something more ergonomic. +/** + * @brief A shared pointer array template that represents a virtual array filled with zeros up to `virtual_size_`, + * but with actual memory usage proportional to the region between `start_` and `end_`. + * + * This structure is designed to optimize memory usage by only allocating memory for a specific subrange + * of the array. The `start_` and `end_` members define the range of indices that are backed by actual memory. + * The rest of the indices, up to `virtual_size_`, are conceptually filled with zero values. + * + * The class allows for sharing the underlying array with potential offset adjustments, making it possible + * to represent shifted arrays where the actual memory-backed range starts from a non-zero index. + * It is designed to be wrapped by another class, namely `Polynomial`, and is not intended to be used directly. + * + * @tparam T The type of the elements in the array. + */ template struct SharedShiftedVirtualZeroesArray { - // Method to set the value at a specific index + + /** + * @brief Sets the value at the specified index. + * + * @param index The index at which the value should be set. + * @param value The value to set. + * @throws Fails in assert mode if the index is not within the memory-backed range [start_, end_). + */ void set(size_t index, const T& value) { - ASSERT(index < size_); - data()[index] = value; + ASSERT(index >= start_ && index < end_); + data()[index - start_] = value; } - // Method to get the value at a specific index - T get(size_t index) const + /** + * @brief Retrieves the value at the specified index, or 'zero'. Optimizes for e.g. 256-bit fields + * by storing a static 0 value, allowing usage of a const reference. + * + * @param index The index from which to retrieve the value. + * @param virtual_padding For the rare case where we explicitly want the 0-returning behavior beyond our usual + * virtual_size. + * @return The value at the specified index, or a default value (e.g. a field zero) of T if the index is outside the + * memory-backed range. + * @throws Fails in assert mode if the index is greater than or equal to `virtual_size_`. + */ + const T& get(size_t index, size_t virtual_padding = 0) const { - ASSERT(index < virtual_size_); - if (index < size_) { - return data()[index]; + static const T zero{}; + ASSERT(index < virtual_size_ + virtual_padding); + if (index >= start_ && index < end_) { + return data()[index - start_]; } - return T{}; // Return default element when index is out of the actual filled size + return zero; // Return default element when index is out of the actual filled size } - T* data() { return backing_memory_.get() + shift_; } - const T* data() const { return backing_memory_.get() + shift_; } + /** + * @brief Returns a pointer to the underlying memory array. + * NOTE: This should be used with care, as index 0 corresponds to virtual index `start_`. + * + * @return A pointer to the beginning of the memory-backed range. + */ + T* data() { return backing_memory_.get(); } + const T* data() const { return backing_memory_.get(); } + // Our size is end_ - start_. Note that we need to offset end_ when doing a shift to + // correctly maintain the size. + size_t size() const { return end_ - start_; } + // Getter for consistency with size(); + size_t virtual_size() const { return virtual_size_; } + + T& operator[](size_t index) + { + ASSERT(index >= start_ && index < end_); + return data()[index - start_]; + } + // get() is more useful, but for completeness with the non-const operator[] + const T& operator[](size_t index) const + { + ASSERT(index >= start_ && index < end_); + return data()[index - start_]; + } // MEMBERS: - // The actual size of the array allocation - // Memory-backed size such that we can set index 0..size()-1. - // Note: We DO NOT reduce our size or virtual size by shift_. This is because - // only support a shift by values that are included in backing_memory_. - // This guarantee is to be upheld by the class that uses SharedShiftedVirtualZeroesArray. - size_t size_ = 0; - // The logical size of the vector, indices size_ to virtual_size - 1 return T{} when indexed. - // This is really mainly used for a debug check that we never index >= virtual_size_; - // Virtual size such that we can get index 0..virtual_size()-1. + /** + * @brief The starting index of the memory-backed range. + * + * Represents the first index in the array that is backed by actual memory. + * This is used to represent polynomial shifts by representing the unshfited polynomials + * with index >= 1 and reducing this by one to divide by x / left shift one. + * Historically, we used memory padding to represent shifts. This is currently implied by start_ (before which we + * consider all values 0). + */ + size_t start_ = 0; + + /** + * @brief The ending index of the memory-backed range. + * + * Represents the first index after `start_` that is not backed by actual memory. + */ + size_t end_ = 0; + + /** + * @brief The total logical size of the array. + * + * This is the size of the array as it would appear to a user, including both the memory-backed + * range and the conceptual zero-filled range beyond `end_` and before `start_` (if a positive value). + */ size_t virtual_size_ = 0; - // An offset into the array, used to implement shifted polynomials. - size_t shift_ = 0; - // The memory + /** + * @brief Shared pointer to the underlying memory array. + * + * The memory is allocated for the range [start_, end_). It is shared across instances to allow + * for efficient memory use when arrays are shifted or otherwise manipulated. + */ // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) std::shared_ptr backing_memory_; }; \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp index 966fb045273..1fd8a652371 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp @@ -2,7 +2,7 @@ #include "barretenberg/protogalaxy/protogalaxy_prover_internal.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/sumcheck/instance/instances.hpp" +#include "barretenberg/ultra_honk/decider_keys.hpp" #include using namespace bb; @@ -21,16 +21,16 @@ TEST(Protogalaxy, CombinerOn2Keys) using Fun = ProtogalaxyProverInternal; const auto restrict_to_standard_arithmetic_relation = [](auto& polys) { - std::fill(polys.q_arith.begin(), polys.q_arith.end(), 1); - std::fill(polys.q_delta_range.begin(), polys.q_delta_range.end(), 0); - std::fill(polys.q_elliptic.begin(), polys.q_elliptic.end(), 0); - std::fill(polys.q_aux.begin(), polys.q_aux.end(), 0); - std::fill(polys.q_lookup.begin(), polys.q_lookup.end(), 0); - std::fill(polys.q_4.begin(), polys.q_4.end(), 0); - std::fill(polys.q_poseidon2_external.begin(), polys.q_poseidon2_external.end(), 0); - std::fill(polys.q_poseidon2_internal.begin(), polys.q_poseidon2_internal.end(), 0); - std::fill(polys.w_4.begin(), polys.w_4.end(), 0); - std::fill(polys.w_4_shift.begin(), polys.w_4_shift.end(), 0); + std::fill(polys.q_arith.coeffs().begin(), polys.q_arith.coeffs().end(), 1); + std::fill(polys.q_delta_range.coeffs().begin(), polys.q_delta_range.coeffs().end(), 0); + std::fill(polys.q_elliptic.coeffs().begin(), polys.q_elliptic.coeffs().end(), 0); + std::fill(polys.q_aux.coeffs().begin(), polys.q_aux.coeffs().end(), 0); + std::fill(polys.q_lookup.coeffs().begin(), polys.q_lookup.coeffs().end(), 0); + std::fill(polys.q_4.coeffs().begin(), polys.q_4.coeffs().end(), 0); + std::fill(polys.q_poseidon2_external.coeffs().begin(), polys.q_poseidon2_external.coeffs().end(), 0); + std::fill(polys.q_poseidon2_internal.coeffs().begin(), polys.q_poseidon2_internal.coeffs().end(), 0); + std::fill(polys.w_4.coeffs().begin(), polys.w_4.coeffs().end(), 0); + std::fill(polys.w_4_shift.coeffs().begin(), polys.w_4_shift.coeffs().end(), 0); }; auto run_test = [&](bool is_random_input) { @@ -90,20 +90,20 @@ TEST(Protogalaxy, CombinerOn2Keys) alphas.fill(bb::Univariate(FF(0))); // focus on the arithmetic relation only const auto create_add_gate = [](auto& polys, const size_t idx, FF w_l, FF w_r) { - polys.w_l[idx] = w_l; - polys.w_r[idx] = w_r; - polys.w_o[idx] = w_l + w_r; - polys.q_l[idx] = 1; - polys.q_r[idx] = 1; - polys.q_o[idx] = -1; + polys.w_l.at(idx) = w_l; + polys.w_r.at(idx) = w_r; + polys.w_o.at(idx) = w_l + w_r; + polys.q_l.at(idx) = 1; + polys.q_r.at(idx) = 1; + polys.q_o.at(idx) = -1; }; const auto create_mul_gate = [](auto& polys, const size_t idx, FF w_l, FF w_r) { - polys.w_l[idx] = w_l; - polys.w_r[idx] = w_r; - polys.w_o[idx] = w_l * w_r; - polys.q_m[idx] = 1; - polys.q_o[idx] = -1; + polys.w_l.at(idx) = w_l; + polys.w_r.at(idx) = w_r; + polys.w_o.at(idx) = w_l * w_r; + polys.q_m.at(idx) = 1; + polys.q_o.at(idx) = -1; }; create_add_gate(keys[0]->proving_key.polynomials, 0, 1, 2); @@ -162,14 +162,14 @@ TEST(Protogalaxy, CombinerOptimizationConsistency) constexpr size_t UNIVARIATE_LENGTH = 12; const auto restrict_to_standard_arithmetic_relation = [](auto& polys) { - std::fill(polys.q_arith.begin(), polys.q_arith.end(), 1); - std::fill(polys.q_delta_range.begin(), polys.q_delta_range.end(), 0); - std::fill(polys.q_elliptic.begin(), polys.q_elliptic.end(), 0); - std::fill(polys.q_aux.begin(), polys.q_aux.end(), 0); - std::fill(polys.q_lookup.begin(), polys.q_lookup.end(), 0); - std::fill(polys.q_4.begin(), polys.q_4.end(), 0); - std::fill(polys.w_4.begin(), polys.w_4.end(), 0); - std::fill(polys.w_4_shift.begin(), polys.w_4_shift.end(), 0); + std::fill(polys.q_arith.coeffs().begin(), polys.q_arith.coeffs().end(), 1); + std::fill(polys.q_delta_range.coeffs().begin(), polys.q_delta_range.coeffs().end(), 0); + std::fill(polys.q_elliptic.coeffs().begin(), polys.q_elliptic.coeffs().end(), 0); + std::fill(polys.q_aux.coeffs().begin(), polys.q_aux.coeffs().end(), 0); + std::fill(polys.q_lookup.coeffs().begin(), polys.q_lookup.coeffs().end(), 0); + std::fill(polys.q_4.coeffs().begin(), polys.q_4.coeffs().end(), 0); + std::fill(polys.w_4.coeffs().begin(), polys.w_4.coeffs().end(), 0); + std::fill(polys.w_4_shift.coeffs().begin(), polys.w_4_shift.coeffs().end(), 0); }; auto run_test = [&](bool is_random_input) { @@ -210,7 +210,7 @@ TEST(Protogalaxy, CombinerOptimizationConsistency) // Get the result of the 0th subrelation of the arithmetic relation FF key_offset = std::get<0>(temporary_accumulator)[0]; // Subtract it from q_c[0] (it directly affect the target sum, making it zero and enabling the optimisation) - keys_data[1]->proving_key.polynomials.q_c[0] -= key_offset; + keys_data[1]->proving_key.polynomials.q_c.at(0) -= key_offset; std::vector extended_polynomials; // These hold the extensions of prover polynomials @@ -224,7 +224,8 @@ TEST(Protogalaxy, CombinerOptimizationConsistency) keys_data[1]->proving_key.polynomials.get_all(), prover_polynomials.get_all())) { for (size_t i = 0; i < /*circuit_size*/ 2; i++) { - new_polynomial[i] = key_0_polynomial[i] + ((key_1_polynomial[i] - key_0_polynomial[i]) * idx); + new_polynomial.at(i) = + key_0_polynomial[i] + ((key_1_polynomial[i] - key_0_polynomial[i]) * idx); } } extended_polynomials.push_back(std::move(prover_polynomials)); @@ -280,20 +281,20 @@ TEST(Protogalaxy, CombinerOptimizationConsistency) alphas.fill(bb::Univariate(FF(0))); // focus on the arithmetic relation only const auto create_add_gate = [](auto& polys, const size_t idx, FF w_l, FF w_r) { - polys.w_l[idx] = w_l; - polys.w_r[idx] = w_r; - polys.w_o[idx] = w_l + w_r; - polys.q_l[idx] = 1; - polys.q_r[idx] = 1; - polys.q_o[idx] = -1; + polys.w_l.at(idx) = w_l; + polys.w_r.at(idx) = w_r; + polys.w_o.at(idx) = w_l + w_r; + polys.q_l.at(idx) = 1; + polys.q_r.at(idx) = 1; + polys.q_o.at(idx) = -1; }; const auto create_mul_gate = [](auto& polys, const size_t idx, FF w_l, FF w_r) { - polys.w_l[idx] = w_l; - polys.w_r[idx] = w_r; - polys.w_o[idx] = w_l * w_r; - polys.q_m[idx] = 1; - polys.q_o[idx] = -1; + polys.w_l.at(idx) = w_l; + polys.w_r.at(idx) = w_r; + polys.w_o.at(idx) = w_l * w_r; + polys.q_m.at(idx) = 1; + polys.q_o.at(idx) = -1; }; create_add_gate(keys[0]->proving_key.polynomials, 0, 1, 2); @@ -339,4 +340,4 @@ TEST(Protogalaxy, CombinerOptimizationConsistency) }; run_test(true); run_test(false); -}; +}; \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp index 016668440f2..cad8fcf7844 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp @@ -1,7 +1,7 @@ #pragma once #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/relations/relation_parameters.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" namespace bb { /** * @brief The result of running the Protogalaxy prover containing a new accumulator as well as the proof data to diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index 59952528415..e6a4fe1d340 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -533,7 +533,7 @@ template class ProtogalaxyTests : public testing::Test { check_accumulator_target_sum_manual(prover_accumulator, true); // Tamper with an accumulator polynomial - prover_accumulator->proving_key.polynomials.w_l[1] = FF::random_element(); + prover_accumulator->proving_key.polynomials.w_l.at(1) = FF::random_element(); check_accumulator_target_sum_manual(prover_accumulator, false); TupleOfKeys insts_2 = construct_keys(1); // just one decider key pair diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_internal.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_internal.hpp index c1013cd3335..4659dce991d 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_internal.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_internal.hpp @@ -71,6 +71,7 @@ template class ProtogalaxyProverInternal { const RelationParameters& relation_parameters) { + BB_OP_COUNT_TIME_NAME("ProtogalaxyProver_::compute_row_evaluations"); const size_t polynomial_size = polynomials.get_polynomial_size(); std::vector full_honk_evaluations(polynomial_size); diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_mega.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_mega.cpp index b87d837a995..3e6afdda97c 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_mega.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_mega.cpp @@ -1,6 +1,6 @@ // Note: this is split up from protogalaxy_prover_impl.hpp for compile performance reasons #include "barretenberg/flavor/flavor.hpp" -#include "barretenberg/sumcheck/instance/instances.hpp" +#include "barretenberg/ultra_honk/decider_keys.hpp" #include "barretenberg/ultra_honk/oink_prover.hpp" #include "protogalaxy_prover_impl.hpp" namespace bb { diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_ultra.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_ultra.cpp index 16d6d3a6ee9..22882e27693 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_ultra.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_ultra.cpp @@ -1,5 +1,5 @@ // Note: this is split up from protogalaxy_prover_impl.hpp for compile performance reasons -#include "barretenberg/sumcheck/instance/instances.hpp" +#include "barretenberg/ultra_honk/decider_keys.hpp" #include "protogalaxy_prover_impl.hpp" // TODO(https://github.com/AztecProtocol/barretenberg/issues/1076) Remove this instantiation. diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.hpp index 62cb343940a..41b7e7d0dd4 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.hpp @@ -3,8 +3,8 @@ #include "barretenberg/protogalaxy/folding_result.hpp" #include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/sumcheck/instance/instances.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/ultra_honk/decider_keys.hpp" namespace bb { template class ProtogalaxyVerifier_ { diff --git a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp index 519f1031b0a..3945c8a3e20 100644 --- a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp @@ -235,7 +235,7 @@ template class DatabusLookupRelationImpl { bool nonzero_read_count = false; for (size_t i = 0; i < circuit_size; ++i) { // Determine if the present row contains a databus operation - auto& q_busread = polynomials.q_busread[i]; + auto q_busread = polynomials.q_busread[i]; if constexpr (bus_idx == 0) { // calldata is_read = q_busread == 1 && polynomials.q_l[i] == 1; nonzero_read_count = polynomials.calldata_read_counts[i] > 0; @@ -252,12 +252,14 @@ template class DatabusLookupRelationImpl { if (is_read || nonzero_read_count) { // TODO(https://github.com/AztecProtocol/barretenberg/issues/940): avoid get_row if possible. auto row = polynomials.get_row(i); // Note: this is a copy. use sparingly! - inverse_polynomial[i] = compute_read_term(row, relation_parameters) * - compute_write_term(row, relation_parameters); + auto value = compute_read_term(row, relation_parameters) * + compute_write_term(row, relation_parameters); + inverse_polynomial.at(i) = value; } } // Compute inverse polynomial I in place by inverting the product at each row - FF::batch_invert(inverse_polynomial); + // Note: zeroes are ignored as they are not used anyway + FF::batch_invert(inverse_polynomial.coeffs()); }; /** diff --git a/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp index fe66475aded..93b793f168b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp @@ -159,15 +159,16 @@ template class LogDerivLookupRelationImpl { for (size_t i = 0; i < circuit_size; ++i) { // We only compute the inverse if this row contains a lookup gate or data that has been looked up - if (polynomials.q_lookup[i] == 1 || polynomials.lookup_read_tags[i] == 1) { + if (polynomials.q_lookup.get(i) == 1 || polynomials.lookup_read_tags.get(i) == 1) { // TODO(https://github.com/AztecProtocol/barretenberg/issues/940): avoid get_row if possible. auto row = polynomials.get_row(i); // Note: this is a copy. use sparingly! - inverse_polynomial[i] = compute_read_term(row, relation_parameters) * - compute_write_term(row, relation_parameters); + auto value = compute_read_term(row, relation_parameters) * + compute_write_term(row, relation_parameters); + inverse_polynomial.at(i) = value; } } // Compute inverse polynomial I in place by inverting the product at each row - FF::batch_invert(inverse_polynomial); + FF::batch_invert(inverse_polynomial.coeffs()); }; /** diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.cpp index 16af14fec8b..eb37760417b 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.cpp @@ -59,7 +59,7 @@ std::shared_ptr> FileCrsFactory::get if (prover_degree_ < degree || !prover_crs_) { prover_crs_ = std::make_shared>(degree, path_); prover_degree_ = degree; - info("Initializing ", Curve::name, " prover CRS from file of size ", degree); + vinfo("Initializing ", Curve::name, " prover CRS from file of size ", degree); } return prover_crs_; } @@ -70,7 +70,7 @@ std::shared_ptr> FileCrsFactory::g if (verifier_degree_ < degree || !verifier_crs_) { verifier_crs_ = std::make_shared>(path_, degree); verifier_degree_ = degree; - info("Initializing ", Curve::name, " verifier CRS from file of size ", degree); + vinfo("Initializing ", Curve::name, " verifier CRS from file of size ", degree); } return verifier_crs_; } diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp index d0938f30602..3dff9aec750 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp @@ -50,15 +50,33 @@ MemBn254CrsFactory::MemBn254CrsFactory(std::vector const& po } verifier_crs_ = std::make_shared(g2_point, g1_identity); + + vinfo("Initializing ", + curve::BN254::name, + " prover CRS from memory with num points = ", + prover_crs_->get_monomial_size()); } -std::shared_ptr> MemBn254CrsFactory::get_prover_crs(size_t) +std::shared_ptr> MemBn254CrsFactory::get_prover_crs(size_t degree) { + if (prover_crs_->get_monomial_size() < degree) { + throw_or_abort(format("prover trying to get too many points in MemGrumpkinCrsFactory! ", + prover_crs_->get_monomial_size(), + " vs ", + degree)); + } return prover_crs_; } -std::shared_ptr> MemBn254CrsFactory::get_verifier_crs(size_t) +std::shared_ptr> MemBn254CrsFactory::get_verifier_crs(size_t degree) { + + if (prover_crs_->get_monomial_size() < degree) { + throw_or_abort(format("verifier trying to get too many points in MemGrumpkinCrsFactory! ", + prover_crs_->get_monomial_size(), + " vs ", + degree)); + } return verifier_crs_; } diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.cpp index f0c3600c869..4a79ec26e62 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.cpp @@ -44,7 +44,12 @@ namespace bb::srs::factories { MemGrumpkinCrsFactory::MemGrumpkinCrsFactory(std::vector const& points) : prover_crs_(std::make_shared>(points)) , verifier_crs_(std::make_shared(points)) -{} +{ + vinfo("Initializing ", + curve::Grumpkin::name, + " prover CRS from memory with num points = ", + prover_crs_->get_monomial_size()); +} std::shared_ptr> MemGrumpkinCrsFactory::get_prover_crs(size_t degree) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.hpp index 57b128601bd..b4b8cec6690 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.hpp @@ -1,6 +1,6 @@ #pragma once #include "barretenberg/honk/proof_system/types/proof.hpp" -#include "barretenberg/stdlib/protogalaxy_verifier/recursive_verifier_instance.hpp" +#include "barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_key.hpp" #include "barretenberg/stdlib/transcript/transcript.hpp" #include "barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp index c05e1499fc5..4292b2b8c95 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp @@ -27,7 +27,7 @@ OinkRecursiveVerifier_::OinkRecursiveVerifier_(Builder* builder, , domain_separator(std::move(domain_separator)) {} -template void OinkRecursiveVerifier_::verify_proof(OinkProof& proof) +template void OinkRecursiveVerifier_::verify_proof(const OinkProof& proof) { transcript = std::make_shared(proof); verify(); @@ -113,9 +113,11 @@ template void OinkRecursiveVerifier_::verify() commitments.z_perm = transcript->template receive_from_prover(domain_separator + labels.z_perm); RelationSeparator alphas; - for (size_t idx = 0; idx < alphas.size(); idx++) { - alphas[idx] = transcript->template get_challenge(domain_separator + "alpha_" + std::to_string(idx)); + std::array args; + for (size_t idx = 0; idx < alphas.size(); ++idx) { + args[idx] = domain_separator + "alpha_" + std::to_string(idx); } + alphas = transcript->template get_challenges(args); verification_key->relation_parameters = RelationParameters{ eta, eta_two, eta_three, beta, gamma, public_input_delta }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp index b8a96fb9e81..5b021062313 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp @@ -1,5 +1,5 @@ #pragma once -#include "barretenberg/stdlib/protogalaxy_verifier/recursive_verifier_instance.hpp" +#include "barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_key.hpp" #include "barretenberg/stdlib/transcript/transcript.hpp" #include "barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" @@ -55,7 +55,7 @@ template class OinkRecursiveVerifier_ { * @brief Constructs an oink recursive verifier circuit for a provided oink proof. * */ - void verify_proof(OinkProof& proof); + void verify_proof(const OinkProof& proof); std::shared_ptr verification_key; Builder* builder; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 08113c94c83..a728f3e3f7e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -25,7 +25,7 @@ UltraRecursiveVerifier_::UltraRecursiveVerifier_(Builder* builder, const */ template UltraRecursiveVerifier_::AggregationObject UltraRecursiveVerifier_::verify_proof( - const HonkProof& proof, aggregation_state agg_obj) + const HonkProof& proof, AggregationObject agg_obj) { StdlibProof stdlib_proof = bb::convert_proof_to_witness(builder, proof); return verify_proof(stdlib_proof, agg_obj); @@ -37,7 +37,7 @@ UltraRecursiveVerifier_::AggregationObject UltraRecursiveVerifier_ UltraRecursiveVerifier_::AggregationObject UltraRecursiveVerifier_::verify_proof( - const StdlibProof& proof, aggregation_state agg_obj) + const StdlibProof& proof, AggregationObject agg_obj) { using Sumcheck = ::bb::SumcheckVerifier; using PCS = typename Flavor::PCS; @@ -59,7 +59,7 @@ UltraRecursiveVerifier_::AggregationObject UltraRecursiveVerifier_recursive_proof_public_inputs_indices - aggregation_state nested_agg_obj; + AggregationObject nested_agg_obj; size_t idx = 0; std::array nested_pairing_points; for (size_t i = 0; i < 2; i++) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp index f231b6c765c..40a2dbe7e91 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp @@ -27,9 +27,8 @@ template class UltraRecursiveVerifier_ { const std::shared_ptr& native_verifier_key); explicit UltraRecursiveVerifier_(Builder* builder, const std::shared_ptr& vkey); - AggregationObject verify_proof(const HonkProof& proof, aggregation_state agg_obj); - AggregationObject verify_proof(const StdlibProof& proof, - aggregation_state agg_obj); + AggregationObject verify_proof(const HonkProof& proof, AggregationObject agg_obj); + AggregationObject verify_proof(const StdlibProof& proof, AggregationObject agg_obj); std::shared_ptr key; std::shared_ptr pcs_verification_key; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp index 427e09e8fa1..b8bc065e463 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp @@ -2,7 +2,7 @@ #include "../circuit_builders/circuit_builders_fwd.hpp" #include "../field/field.hpp" #include "barretenberg/stdlib/primitives/curves/bn254.hpp" -#include "barretenberg/stdlib/protogalaxy_verifier/recursive_instances.hpp" +#include "barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_keys.hpp" #include "barretenberg/stdlib_circuit_builders/databus.hpp" namespace bb::stdlib { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_conversion.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_conversion.hpp index a1ca8703c6b..a326a53dc6d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_conversion.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field_conversion.hpp @@ -161,4 +161,22 @@ template std::vector> convert_to_bn25 } } +/** + * @brief Deserialize an object of specified type from a buffer of field elements; update provided read count in place + * + * @tparam TargetType Type to reconstruct from buffer of field elements + * @param builder + * @param elements Buffer of field elements + * @param num_frs_read Index at which to read into buffer + */ +template +TargetType deserialize_from_frs(Builder& builder, std::span> elements, size_t& num_frs_read) +{ + size_t num_frs = calc_num_bn254_frs(); + ASSERT(elements.size() >= num_frs_read + num_frs); + TargetType result = convert_from_bn254_frs(builder, elements.subspan(num_frs_read, num_frs)); + num_frs_read += num_frs; + return result; +} + } // namespace bb::stdlib::field_conversion \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.cpp index 593fdfa6aa8..789c5eb7627 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.cpp @@ -1446,5 +1446,6 @@ template cycle_group cycle_group::operator/ template class cycle_group; template class cycle_group; template class cycle_group; +template struct cycle_group::cycle_scalar; } // namespace bb::stdlib diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.hpp index 182295ff839..8a9b7ff0620 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.hpp @@ -66,7 +66,7 @@ template class cycle_group { * free from the `batch_mul` algorithm, making the range checks performed by `bigfield` largely redundant. */ struct cycle_scalar { - static constexpr size_t LO_BITS = plookup::FixedBaseParams::BITS_PER_LO_SCALAR; + static constexpr size_t LO_BITS = field_t::native::Params::MAX_BITS_PER_ENDOMORPHISM_SCALAR; static constexpr size_t HI_BITS = NUM_BITS - LO_BITS; field_t lo; field_t hi; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.cpp index ad19ca6a681..b64d0b09f38 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.cpp @@ -1,6 +1,6 @@ #include "protogalaxy_recursive_verifier.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_delta.hpp" -#include "barretenberg/stdlib/protogalaxy_verifier/recursive_instances.hpp" +#include "barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_keys.hpp" namespace bb::stdlib::recursion::honk { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.hpp index 31935f8c561..fc1202cc071 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.hpp @@ -3,7 +3,7 @@ #include "barretenberg/honk/proof_system/types/proof.hpp" #include "barretenberg/protogalaxy/folding_result.hpp" #include "barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp" -#include "barretenberg/stdlib/protogalaxy_verifier/recursive_instances.hpp" +#include "barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_keys.hpp" #include "barretenberg/stdlib/transcript/transcript.hpp" #include "barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp index 88ff343ab79..dfcc4690a34 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp @@ -8,7 +8,7 @@ #include "barretenberg/stdlib/honk_verifier/decider_recursive_verifier.hpp" #include "barretenberg/stdlib/primitives/curves/bn254.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" -#include "barretenberg/sumcheck/instance/instances.hpp" +#include "barretenberg/ultra_honk/decider_keys.hpp" #include "barretenberg/ultra_honk/decider_prover.hpp" #include "barretenberg/ultra_honk/decider_verifier.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" @@ -361,7 +361,7 @@ template class ProtogalaxyRecursiveTests : public tes auto verification_key = std::make_shared(prover_inst->proving_key); auto verifier_inst = std::make_shared(verification_key); - prover_accumulator->proving_key.polynomials.w_l[1] = FF::random_element(); + prover_accumulator->proving_key.polynomials.w_l.at(1) = FF::random_element(); // Generate a folding proof with the incorrect polynomials which would result in the prover having the wrong // target sum diff --git a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_verifier_instance.hpp b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_key.hpp similarity index 95% rename from barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_verifier_instance.hpp rename to barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_key.hpp index bc536d781c1..c0278b48d61 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_verifier_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_key.hpp @@ -2,7 +2,7 @@ #include "barretenberg/commitment_schemes/verification_key.hpp" #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/relations/relation_parameters.hpp" -#include "barretenberg/sumcheck/instance/verifier_instance.hpp" +#include "barretenberg/ultra_honk/decider_verification_key.hpp" namespace bb::stdlib::recursion::honk { @@ -22,6 +22,7 @@ template class RecursiveDeciderVerificationKey_ { using Builder = typename Flavor::CircuitBuilder; using NativeFlavor = typename Flavor::NativeFlavor; using DeciderVerificationKey = bb::DeciderVerificationKey_; + using VerifierCommitmentKey = typename NativeFlavor::VerifierCommitmentKey; Builder* builder; @@ -101,7 +102,9 @@ template class RecursiveDeciderVerificationKey_ { { auto native_honk_vk = std::make_shared(verification_key->circuit_size, verification_key->num_public_inputs); - native_honk_vk->pcs_verification_key = verification_key->pcs_verification_key; + native_honk_vk->pcs_verification_key = verification_key->pcs_verification_key == nullptr + ? std::make_shared() + : verification_key->pcs_verification_key; native_honk_vk->pub_inputs_offset = verification_key->pub_inputs_offset; native_honk_vk->contains_recursive_proof = verification_key->contains_recursive_proof; native_honk_vk->recursive_proof_public_input_indices = verification_key->recursive_proof_public_input_indices; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_instances.hpp b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_keys.hpp similarity index 94% rename from barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_instances.hpp rename to barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_keys.hpp index c168fdd3b12..eadd7d8a656 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_instances.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_keys.hpp @@ -1,7 +1,7 @@ #pragma once #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/relations/relation_parameters.hpp" -#include "barretenberg/stdlib/protogalaxy_verifier/recursive_verifier_instance.hpp" +#include "barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_key.hpp" namespace bb::stdlib::recursion::honk { template struct RecursiveDeciderVerificationKeys_ { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.hpp index 3bc2e70d156..a46966afb7a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.hpp @@ -3,8 +3,8 @@ #include "barretenberg/crypto/poseidon2/poseidon2.hpp" #include "barretenberg/stdlib/hash/poseidon2/poseidon2.hpp" #include "barretenberg/stdlib/primitives/field/field_conversion.hpp" +#include "barretenberg/stdlib/primitives/group/cycle_group.hpp" #include "barretenberg/transcript/transcript.hpp" - namespace bb::stdlib::recursion::honk { template struct StdlibTranscriptParams { @@ -19,7 +19,23 @@ template struct StdlibTranscriptParams { Builder* builder = data[0].get_context(); return stdlib::poseidon2::hash(*builder, data); } - + /** + * @brief Split a challenge field element into two half-width challenges + * @details `lo` is 128 bits and `hi` is 126 bits. + * This should provide significantly more than our security parameter bound: 100 bits + * + * @param challenge + * @return std::array + */ + static inline std::array split_challenge(const Fr& challenge) + { + // use existing field-splitting code in cycle_scalar + using cycle_scalar = typename stdlib::cycle_group::cycle_scalar; + const cycle_scalar scalar = cycle_scalar(challenge); + scalar.lo.create_range_constraint(cycle_scalar::LO_BITS); + scalar.hi.create_range_constraint(cycle_scalar::HI_BITS); + return std::array{ scalar.lo, scalar.hi }; + } template static inline T convert_challenge(const Fr& challenge) { Builder* builder = challenge.get_context(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.test.cpp index 6369a7149a2..0344b1f8835 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.test.cpp @@ -6,8 +6,8 @@ #include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_simulator.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_simulator.hpp index 1453291b318..7734a0d90d5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_simulator.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_simulator.hpp @@ -1,5 +1,7 @@ #pragma once +#include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" #include "barretenberg/plonk_honk_shared/arithmetization/gate_data.hpp" #include "barretenberg/plonk_honk_shared/types/aggregation_object_type.hpp" #include "barretenberg/plonk_honk_shared/types/circuit_type.hpp" @@ -38,6 +40,7 @@ namespace bb { class CircuitSimulatorBN254 { public: using FF = bb::fr; + using EmbeddedCurve = std::conditional_t, curve::BN254, curve::Grumpkin>; static constexpr CircuitType CIRCUIT_TYPE = CircuitType::ULTRA; static constexpr std::string_view NAME_STRING = "SIMULATOR"; bool contains_recursive_proof = false; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/databus.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/databus.hpp index dca1e522f5f..98f815822d2 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/databus.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/databus.hpp @@ -68,6 +68,8 @@ enum class BusId { CALLDATA, SECONDARY_CALLDATA, RETURNDATA }; * */ struct DatabusPropagationData { + bool operator==(const DatabusPropagationData&) const = default; + // Flags indicating whether the public inputs contain commitment(s) to app/kernel return data bool contains_app_return_data_commitment = false; bool contains_kernel_return_data_commitment = false; @@ -80,6 +82,12 @@ struct DatabusPropagationData { // Is this a kernel circuit (used to determine when databus consistency checks can be appended to a circuit in IVC) bool is_kernel = false; + + MSGPACK_FIELDS(contains_app_return_data_commitment, + contains_kernel_return_data_commitment, + app_return_data_public_input_idx, + kernel_return_data_public_input_idx, + is_kernel); }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/flavor_serialization.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/flavor_serialization.test.cpp new file mode 100644 index 00000000000..46b73cbbfe4 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/flavor_serialization.test.cpp @@ -0,0 +1,65 @@ +#include "barretenberg/common/serialize.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/plonk_honk_shared/library/grand_product_delta.hpp" +#include "barretenberg/relations/permutation_relation.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" +#include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" +#include "barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include "barretenberg/sumcheck/sumcheck_round.hpp" +#include "barretenberg/ultra_honk/ultra_prover.hpp" +#include "barretenberg/ultra_honk/ultra_verifier.hpp" + +#include + +using namespace bb; + +template class FlavorSerializationTests : public ::testing::Test { + public: + using Builder = typename Flavor::CircuitBuilder; + using DeciderProvingKey = DeciderProvingKey_; + using VerificationKey = typename Flavor::VerificationKey; + + protected: + static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } +}; + +using FlavorTypes = testing::Types; +TYPED_TEST_SUITE(FlavorSerializationTests, FlavorTypes); + +// Test msgpack serialization/deserialization of verification keys +TYPED_TEST(FlavorSerializationTests, VerificationKeySerialization) +{ + using Builder = typename TestFixture::Builder; + using DeciderProvingKey = typename TestFixture::DeciderProvingKey; + using VerificationKey = typename TestFixture::VerificationKey; + + Builder builder; + + // Add some arbitrary arithmetic gates that utilize public inputs + MockCircuits::add_arithmetic_gates_with_public_inputs(builder, /*num_gates=*/100); + + auto proving_key = std::make_shared(builder); + VerificationKey original_vkey{ proving_key->proving_key }; + + // Set the pcs ptr to null since this will not be reconstructed correctly from buffer + original_vkey.pcs_verification_key = nullptr; + + // Populate some non-zero values in the databus_propagation_data to ensure its being handled + if constexpr (IsMegaBuilder) { + original_vkey.databus_propagation_data.contains_app_return_data_commitment = 1; + original_vkey.databus_propagation_data.contains_kernel_return_data_commitment = 1; + original_vkey.databus_propagation_data.app_return_data_public_input_idx = 2; + original_vkey.databus_propagation_data.kernel_return_data_public_input_idx = 4; + original_vkey.databus_propagation_data.is_kernel = 1; + } + + // Serialize and deserialize the verification key + std::vector vkey_buffer = to_buffer(original_vkey); + VerificationKey deserialized_vkey = from_buffer(vkey_buffer); + + // Ensure the original is equal to the reconstructed + EXPECT_EQ(original_vkey, deserialized_vkey); +} diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp index 845a1ea28f6..791242f61f4 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp @@ -13,20 +13,6 @@ template class GrandProductTests : public testing::Test { public: void SetUp() { srs::init_crs_factory("../srs_db/ignition"); } - /** - * @brief Get a random polynomial - * - * @param size - * @return Polynomial - */ - static constexpr Polynomial get_random_polynomial(size_t size) - { - Polynomial random_polynomial{ size }; - for (auto& coeff : random_polynomial) { - coeff = FF::random_element(); - } - return random_polynomial; - } static void populate_span(auto& polynomial_view, const auto& polynomial) { @@ -53,8 +39,13 @@ template class GrandProductTests : public testing::Test { // Construct a ProverPolynomials object with completely random polynomials ProverPolynomials prover_polynomials; + for (auto& poly : prover_polynomials.get_to_be_shifted()) { + poly = Polynomial::random(circuit_size, /*shiftable*/ 1); + } for (auto& poly : prover_polynomials.get_all()) { - poly = get_random_polynomial(circuit_size); + if (poly.is_empty()) { + poly = Polynomial::random(circuit_size); + } } // Get random challenges @@ -136,10 +127,10 @@ template class GrandProductTests : public testing::Test { // Step (4) Polynomial z_permutation_expected(circuit_size); - z_permutation_expected[0] = FF::zero(); // Z_0 = 1 + z_permutation_expected.at(0) = FF::zero(); // Z_0 = 1 // Note: in practice, we replace this expensive element-wise division with Montgomery batch inversion for (size_t i = 0; i < circuit_size - 1; ++i) { - z_permutation_expected[i + 1] = numerator_accum[0][i] / denominator_accum[0][i]; + z_permutation_expected.at(i + 1) = numerator_accum[0][i] / denominator_accum[0][i]; } // Check consistency between locally computed z_perm and the one computed by the prover library diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp index 783df2c0167..0ff86bf9070 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp @@ -35,6 +35,7 @@ class MegaFlavor { using Polynomial = bb::Polynomial; using CommitmentKey = bb::CommitmentKey; using VerifierCommitmentKey = bb::VerifierCommitmentKey; + using TraceBlocks = CircuitBuilder::Arithmetization::TraceBlocks; // Indicates that this flavor runs with non-ZK Sumcheck. static constexpr bool HasZK = false; @@ -104,6 +105,7 @@ class MegaFlavor { */ template class PrecomputedEntities : public PrecomputedEntitiesBase { public: + bool operator==(const PrecomputedEntities&) const = default; using DataType = DataType_; DEFINE_FLAVOR_MEMBERS(DataType, q_m, // column 0 @@ -372,13 +374,24 @@ class MegaFlavor { public: // Define all operations as default, except copy construction/assignment ProverPolynomials() = default; + // fully-formed constructor ProverPolynomials(size_t circuit_size) - { // Initialize all unshifted polynomials to the zero polynomial and initialize the shifted polys + { // TODO(https://github.com/AztecProtocol/barretenberg/issues/1072): Unexpected jump in time to allocate all // of these polys (in aztec_ivc_bench only). BB_OP_COUNT_TIME_NAME("ProverPolynomials(size_t)"); + + for (auto& poly : get_to_be_shifted()) { + poly = Polynomial{ /*memory size*/ circuit_size - 1, + /*largest possible index*/ circuit_size, + /* offset */ 1 }; + } + // catch-all with fully formed polynomials for (auto& poly : get_unshifted()) { - poly = Polynomial{ circuit_size }; + if (poly.is_empty()) { + // Not set above + poly = Polynomial{ /*memory size*/ circuit_size, /*largest possible index*/ circuit_size }; + } } set_shifted(); } @@ -390,6 +403,7 @@ class MegaFlavor { [[nodiscard]] size_t get_polynomial_size() const { return q_c.size(); } [[nodiscard]] AllValues get_row(size_t row_idx) const { + BB_OP_COUNT_TIME_NAME("MegaFlavor::get_row"); AllValues result; for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) { result_field = polynomial[row_idx]; @@ -445,17 +459,17 @@ class MegaFlavor { // Compute read record values for (const auto& gate_idx : memory_read_records) { - wires[3][gate_idx] += wires[2][gate_idx] * eta_three; - wires[3][gate_idx] += wires[1][gate_idx] * eta_two; - wires[3][gate_idx] += wires[0][gate_idx] * eta; + wires[3].at(gate_idx) += wires[2][gate_idx] * eta_three; + wires[3].at(gate_idx) += wires[1][gate_idx] * eta_two; + wires[3].at(gate_idx) += wires[0][gate_idx] * eta; } // Compute write record values for (const auto& gate_idx : memory_write_records) { - wires[3][gate_idx] += wires[2][gate_idx] * eta_three; - wires[3][gate_idx] += wires[1][gate_idx] * eta_two; - wires[3][gate_idx] += wires[0][gate_idx] * eta; - wires[3][gate_idx] += 1; + wires[3].at(gate_idx) += wires[2][gate_idx] * eta_three; + wires[3].at(gate_idx) += wires[1][gate_idx] * eta_two; + wires[3].at(gate_idx) += wires[0][gate_idx] * eta; + wires[3].at(gate_idx) += 1; } } @@ -519,6 +533,7 @@ class MegaFlavor { // Data pertaining to transfer of databus return data via public inputs of the proof being recursively verified DatabusPropagationData databus_propagation_data; + bool operator==(const VerificationKey&) const = default; VerificationKey() = default; VerificationKey(const size_t circuit_size, const size_t num_public_inputs) : VerificationKey_(circuit_size, num_public_inputs) @@ -543,12 +558,47 @@ class MegaFlavor { commitment = proving_key.commitment_key->commit(polynomial); } } + + /** + * @brief Serialize verification key to field elements + */ + std::vector to_field_elements() + { + using namespace bb::field_conversion; + + auto serialize_to_field_buffer = [](const auto& input, std::vector& buffer) { + std::vector input_fields = convert_to_bn254_frs(input); + buffer.insert(buffer.end(), input_fields.begin(), input_fields.end()); + }; + + std::vector elements; + + serialize_to_field_buffer(this->circuit_size, elements); + serialize_to_field_buffer(this->num_public_inputs, elements); + serialize_to_field_buffer(this->pub_inputs_offset, elements); + serialize_to_field_buffer(this->contains_recursive_proof, elements); + serialize_to_field_buffer(this->recursive_proof_public_input_indices, elements); + + serialize_to_field_buffer(this->databus_propagation_data.contains_app_return_data_commitment, elements); + serialize_to_field_buffer(this->databus_propagation_data.contains_kernel_return_data_commitment, elements); + serialize_to_field_buffer(this->databus_propagation_data.app_return_data_public_input_idx, elements); + serialize_to_field_buffer(this->databus_propagation_data.kernel_return_data_public_input_idx, elements); + serialize_to_field_buffer(this->databus_propagation_data.is_kernel, elements); + + for (Commitment& commitment : this->get_all()) { + serialize_to_field_buffer(commitment, elements); + } + + return elements; + } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/964): Clean the boilerplate up. VerificationKey(const size_t circuit_size, const size_t num_public_inputs, const size_t pub_inputs_offset, const bool contains_recursive_proof, const AggregationObjectPubInputIndices& recursive_proof_public_input_indices, + const DatabusPropagationData& databus_propagation_data, const Commitment& q_m, const Commitment& q_c, const Commitment& q_l, @@ -586,6 +636,7 @@ class MegaFlavor { this->pub_inputs_offset = pub_inputs_offset; this->contains_recursive_proof = contains_recursive_proof; this->recursive_proof_public_input_indices = recursive_proof_public_input_indices; + this->databus_propagation_data = databus_propagation_data; this->q_m = q_m; this->q_c = q_c; this->q_l = q_l; @@ -623,6 +674,7 @@ class MegaFlavor { pub_inputs_offset, contains_recursive_proof, recursive_proof_public_input_indices, + databus_propagation_data, q_m, q_c, q_l, diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp index 388de27414f..f650f4b2761 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp @@ -140,42 +140,58 @@ template class MegaRecursiveFlavor_ { */ VerificationKey(CircuitBuilder& builder, std::span elements) { - // deserialize circuit size + using namespace bb::stdlib::field_conversion; + size_t num_frs_read = 0; - size_t num_frs_FF = bb::stdlib::field_conversion::calc_num_bn254_frs(); - size_t num_frs_Comm = bb::stdlib::field_conversion::calc_num_bn254_frs(); - - this->circuit_size = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_FF)) - .get_value()); - num_frs_read += num_frs_FF; - this->num_public_inputs = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_FF)) - .get_value()); - num_frs_read += num_frs_FF; - - this->pub_inputs_offset = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_FF)) - .get_value()); - num_frs_read += num_frs_FF; - this->contains_recursive_proof = bool(stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_FF)) - .get_value()); - num_frs_read += num_frs_FF; - - for (uint32_t i = 0; i < bb::AGGREGATION_OBJECT_SIZE; ++i) { - this->recursive_proof_public_input_indices[i] = - uint32_t(stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_FF)) - .get_value()); - num_frs_read += num_frs_FF; + + this->circuit_size = uint64_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->log_circuit_size = numeric::get_msb(this->circuit_size); + this->num_public_inputs = uint64_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->pub_inputs_offset = uint64_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->contains_recursive_proof = + bool(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + + for (uint32_t& idx : this->recursive_proof_public_input_indices) { + idx = uint32_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + } + + this->databus_propagation_data.contains_app_return_data_commitment = + bool(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->databus_propagation_data.contains_kernel_return_data_commitment = + bool(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->databus_propagation_data.app_return_data_public_input_idx = + uint32_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->databus_propagation_data.kernel_return_data_public_input_idx = + uint32_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->databus_propagation_data.is_kernel = + bool(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + + for (Commitment& commitment : this->get_all()) { + commitment = deserialize_from_frs(builder, elements, num_frs_read); + } + + if (num_frs_read != elements.size()) { + info("Warning: Invalid buffer length in VerificationKey constuctor from fields!"); + ASSERT(false); } + } - for (Commitment& comm : this->get_all()) { - comm = bb::stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_Comm)); - num_frs_read += num_frs_Comm; + /** + * @brief Construct a VerificationKey from a set of corresponding witness indices + * + * @param builder + * @param witness_indices + * @return VerificationKey + */ + static VerificationKey from_witness_indices(CircuitBuilder& builder, + const std::span& witness_indices) + { + std::vector vkey_fields; + vkey_fields.reserve(witness_indices.size()); + for (const auto& idx : witness_indices) { + vkey_fields.emplace_back(FF::from_witness_index(&builder, idx)); } + return VerificationKey(builder, vkey_fields); } }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp index cfcfa41a70c..b87b30f356d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp @@ -48,7 +48,7 @@ template void UltraCircuitBuilder_:: circuit_finalized = true; } else { // Gates added after first call to finalize will not be processed since finalization is only performed once - info("WARNING: Redudant call to finalize_circuit(). Is this intentional?"); + info("WARNING: Redundant call to finalize_circuit(). Is this intentional?"); } } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp index c8270ecfe5c..2bb9cb89721 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp @@ -105,6 +105,7 @@ class UltraFlavor { */ template class PrecomputedEntities : public PrecomputedEntitiesBase { public: + bool operator==(const PrecomputedEntities&) const = default; using DataType = DataType_; DEFINE_FLAVOR_MEMBERS(DataType, q_m, // column 0 @@ -293,11 +294,18 @@ class UltraFlavor { // Define all operations as default, except copy construction/assignment ProverPolynomials() = default; ProverPolynomials(size_t circuit_size) - { // Initialize all unshifted polynomials to the zero polynomial and initialize the - // shifted polys + { ZoneScopedN("creating empty prover polys"); + for (auto& poly : get_to_be_shifted()) { + poly = Polynomial{ /*memory size*/ circuit_size - 1, + /*largest possible index*/ circuit_size, + /* offset */ 1 }; + } for (auto& poly : get_unshifted()) { - poly = Polynomial{ circuit_size }; + if (poly.is_empty()) { + // Not set above + poly = Polynomial{ /*fully formed*/ circuit_size }; + } } set_shifted(); } @@ -309,6 +317,7 @@ class UltraFlavor { [[nodiscard]] size_t get_polynomial_size() const { return q_c.size(); } [[nodiscard]] AllValues get_row(const size_t row_idx) const { + BB_OP_COUNT_TIME(); AllValues result; for (auto [result_field, polynomial] : zip_view(result.get_all(), get_all())) { result_field = polynomial[row_idx]; @@ -361,17 +370,17 @@ class UltraFlavor { // Compute read record values for (const auto& gate_idx : memory_read_records) { - wires[3][gate_idx] += wires[2][gate_idx] * eta_three; - wires[3][gate_idx] += wires[1][gate_idx] * eta_two; - wires[3][gate_idx] += wires[0][gate_idx] * eta; + wires[3].at(gate_idx) += wires[2][gate_idx] * eta_three; + wires[3].at(gate_idx) += wires[1][gate_idx] * eta_two; + wires[3].at(gate_idx) += wires[0][gate_idx] * eta; } // Compute write record values for (const auto& gate_idx : memory_write_records) { - wires[3][gate_idx] += wires[2][gate_idx] * eta_three; - wires[3][gate_idx] += wires[1][gate_idx] * eta_two; - wires[3][gate_idx] += wires[0][gate_idx] * eta; - wires[3][gate_idx] += 1; + wires[3].at(gate_idx) += wires[2][gate_idx] * eta_three; + wires[3].at(gate_idx) += wires[1][gate_idx] * eta_two; + wires[3].at(gate_idx) += wires[0][gate_idx] * eta; + wires[3].at(gate_idx) += 1; } } @@ -418,6 +427,7 @@ class UltraFlavor { */ class VerificationKey : public VerificationKey_, VerifierCommitmentKey> { public: + bool operator==(const VerificationKey&) const = default; VerificationKey() = default; VerificationKey(const size_t circuit_size, const size_t num_public_inputs) : VerificationKey_(circuit_size, num_public_inputs) diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_keccak.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_keccak_flavor.hpp similarity index 88% rename from barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_keccak.hpp rename to barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_keccak_flavor.hpp index 4e9e8fe67af..0b9485e4122 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_keccak.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_keccak_flavor.hpp @@ -14,6 +14,8 @@ #include "barretenberg/relations/elliptic_relation.hpp" #include "barretenberg/relations/logderiv_lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" +#include "barretenberg/relations/poseidon2_external_relation.hpp" +#include "barretenberg/relations/poseidon2_internal_relation.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" @@ -21,7 +23,6 @@ namespace bb { -// TODO(https://github.com/AztecProtocol/barretenberg/issues/1078): Update flavor to support Poseidon relation. class UltraKeccakFlavor { public: using CircuitBuilder = UltraCircuitBuilder; @@ -39,10 +40,10 @@ class UltraKeccakFlavor { static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. - static constexpr size_t NUM_ALL_ENTITIES = 42; + static constexpr size_t NUM_ALL_ENTITIES = 44; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. - static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 25; + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 27; // The total number of witness entities not including shifts. static constexpr size_t NUM_WITNESS_ENTITIES = 8; // The total number of witnesses including shifts and derived entities. @@ -59,11 +60,14 @@ class UltraKeccakFlavor { bb::LogDerivLookupRelation, bb::DeltaRangeConstraintRelation, bb::EllipticRelation, - bb::AuxiliaryRelation>; + bb::AuxiliaryRelation, + bb::Poseidon2ExternalRelation, + bb::Poseidon2InternalRelation>; + using Relations = Relations_; static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); - static_assert(MAX_PARTIAL_RELATION_LENGTH == 6); + static_assert(MAX_PARTIAL_RELATION_LENGTH == 7); static constexpr size_t MAX_TOTAL_RELATION_LENGTH = compute_max_total_relation_length(); static_assert(MAX_TOTAL_RELATION_LENGTH == 11); static constexpr size_t NUM_SUBRELATIONS = compute_number_of_subrelations(); @@ -102,37 +106,51 @@ class UltraKeccakFlavor { public: using DataType = DataType_; DEFINE_FLAVOR_MEMBERS(DataType, - q_m, // column 0 - q_c, // column 1 - q_l, // column 2 - q_r, // column 3 - q_o, // column 4 - q_4, // column 5 - q_arith, // column 6 - q_delta_range, // column 7 - q_elliptic, // column 8 - q_aux, // column 9 - q_lookup, // column 10 - sigma_1, // column 11 - sigma_2, // column 12 - sigma_3, // column 13 - sigma_4, // column 14 - id_1, // column 15 - id_2, // column 16 - id_3, // column 17 - id_4, // column 18 - table_1, // column 19 - table_2, // column 20 - table_3, // column 21 - table_4, // column 22 - lagrange_first, // column 23 - lagrange_last) // column 24 + q_m, // column 0 + q_c, // column 1 + q_l, // column 2 + q_r, // column 3 + q_o, // column 4 + q_4, // column 5 + q_arith, // column 6 + q_delta_range, // column 7 + q_elliptic, // column 8 + q_aux, // column 9 + q_lookup, // column 10 + q_poseidon2_external, // column 11 + q_poseidon2_internal, // column 12 + sigma_1, // column 13 + sigma_2, // column 14 + sigma_3, // column 15 + sigma_4, // column 16 + id_1, // column 17 + id_2, // column 18 + id_3, // column 19 + id_4, // column 20 + table_1, // column 21 + table_2, // column 22 + table_3, // column 23 + table_4, // column 24 + lagrange_first, // column 25 + lagrange_last) // column 26 static constexpr CircuitType CIRCUIT_TYPE = CircuitBuilder::CIRCUIT_TYPE; auto get_selectors() { - return RefArray{ q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_delta_range, q_elliptic, q_aux, q_lookup }; + return RefArray{ q_m, + q_c, + q_l, + q_r, + q_o, + q_4, + q_arith, + q_delta_range, + q_elliptic, + q_aux, + q_lookup, + q_poseidon2_external, + q_poseidon2_internal }; }; auto get_sigma_polynomials() { return RefArray{ sigma_1, sigma_2, sigma_3, sigma_4 }; }; auto get_id_polynomials() { return RefArray{ id_1, id_2, id_3, id_4 }; }; @@ -243,8 +261,17 @@ class UltraKeccakFlavor { ProverPolynomials(size_t circuit_size) { // Initialize all unshifted polynomials to the zero polynomial and initialize the // shifted polys + + for (auto& poly : get_to_be_shifted()) { + poly = Polynomial{ /*memory size*/ circuit_size - 1, + /*largest possible index*/ circuit_size, + /* offset */ 1 }; + } for (auto& poly : get_unshifted()) { - poly = Polynomial{ circuit_size }; + if (poly.is_empty()) { + // Not set above + poly = Polynomial{ /*memory size*/ circuit_size, /*largest possible index*/ circuit_size }; + } } set_shifted(); } @@ -256,6 +283,7 @@ class UltraKeccakFlavor { [[nodiscard]] size_t get_polynomial_size() const { return q_c.size(); } [[nodiscard]] AllValues get_row(const size_t row_idx) const { + BB_OP_COUNT_TIME(); AllValues result; for (auto [result_field, polynomial] : zip_view(result.get_all(), get_all())) { result_field = polynomial[row_idx]; @@ -308,17 +336,17 @@ class UltraKeccakFlavor { // Compute read record values for (const auto& gate_idx : memory_read_records) { - wires[3][gate_idx] += wires[2][gate_idx] * eta_three; - wires[3][gate_idx] += wires[1][gate_idx] * eta_two; - wires[3][gate_idx] += wires[0][gate_idx] * eta; + wires[3].at(gate_idx) += wires[2][gate_idx] * eta_three; + wires[3].at(gate_idx) += wires[1][gate_idx] * eta_two; + wires[3].at(gate_idx) += wires[0][gate_idx] * eta; } // Compute write record values for (const auto& gate_idx : memory_write_records) { - wires[3][gate_idx] += wires[2][gate_idx] * eta_three; - wires[3][gate_idx] += wires[1][gate_idx] * eta_two; - wires[3][gate_idx] += wires[0][gate_idx] * eta; - wires[3][gate_idx] += 1; + wires[3].at(gate_idx) += wires[2][gate_idx] * eta_three; + wires[3].at(gate_idx) += wires[1][gate_idx] * eta_two; + wires[3].at(gate_idx) += wires[0][gate_idx] * eta; + wires[3].at(gate_idx) += 1; } } @@ -397,6 +425,8 @@ class UltraKeccakFlavor { const Commitment& q_elliptic, const Commitment& q_aux, const Commitment& q_lookup, + const Commitment& q_poseidon2_external, + const Commitment& q_poseidon2_internal, const Commitment& sigma_1, const Commitment& sigma_2, const Commitment& sigma_3, @@ -427,6 +457,8 @@ class UltraKeccakFlavor { this->q_elliptic = q_elliptic; this->q_aux = q_aux; this->q_lookup = q_lookup; + this->q_poseidon2_external = q_poseidon2_external; + this->q_poseidon2_internal = q_poseidon2_internal; this->sigma_1 = sigma_1; this->sigma_2 = sigma_2; this->sigma_3 = sigma_3; @@ -459,6 +491,8 @@ class UltraKeccakFlavor { q_elliptic, q_aux, q_lookup, + q_poseidon2_external, + q_poseidon2_internal, sigma_1, sigma_2, sigma_3, @@ -544,6 +578,8 @@ class UltraKeccakFlavor { q_elliptic = "Q_ELLIPTIC"; q_aux = "Q_AUX"; q_lookup = "Q_LOOKUP"; + q_poseidon2_external = "Q_POSEIDON2_EXTERNAL"; + q_poseidon2_internal = "Q_POSEIDON2_INTERNAL"; sigma_1 = "SIGMA_1"; sigma_2 = "SIGMA_2"; sigma_3 = "SIGMA_3"; @@ -583,6 +619,8 @@ class UltraKeccakFlavor { this->q_elliptic = verification_key->q_elliptic; this->q_aux = verification_key->q_aux; this->q_lookup = verification_key->q_lookup; + this->q_poseidon2_external = verification_key->q_poseidon2_external; + this->q_poseidon2_internal = verification_key->q_poseidon2_internal; this->sigma_1 = verification_key->sigma_1; this->sigma_2 = verification_key->sigma_2; this->sigma_3 = verification_key->sigma_3; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp index 04ff64f28c2..5cb743e26e6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp @@ -125,33 +125,11 @@ template class UltraRecursiveFlavor_ { this->pub_inputs_offset = native_key->pub_inputs_offset; this->contains_recursive_proof = native_key->contains_recursive_proof; this->recursive_proof_public_input_indices = native_key->recursive_proof_public_input_indices; - this->q_m = Commitment::from_witness(builder, native_key->q_m); - this->q_l = Commitment::from_witness(builder, native_key->q_l); - this->q_r = Commitment::from_witness(builder, native_key->q_r); - this->q_o = Commitment::from_witness(builder, native_key->q_o); - this->q_4 = Commitment::from_witness(builder, native_key->q_4); - this->q_c = Commitment::from_witness(builder, native_key->q_c); - this->q_arith = Commitment::from_witness(builder, native_key->q_arith); - this->q_delta_range = Commitment::from_witness(builder, native_key->q_delta_range); - this->q_elliptic = Commitment::from_witness(builder, native_key->q_elliptic); - this->q_aux = Commitment::from_witness(builder, native_key->q_aux); - this->q_lookup = Commitment::from_witness(builder, native_key->q_lookup); - this->q_poseidon2_external = Commitment::from_witness(builder, native_key->q_poseidon2_external); - this->q_poseidon2_internal = Commitment::from_witness(builder, native_key->q_poseidon2_internal); - this->sigma_1 = Commitment::from_witness(builder, native_key->sigma_1); - this->sigma_2 = Commitment::from_witness(builder, native_key->sigma_2); - this->sigma_3 = Commitment::from_witness(builder, native_key->sigma_3); - this->sigma_4 = Commitment::from_witness(builder, native_key->sigma_4); - this->id_1 = Commitment::from_witness(builder, native_key->id_1); - this->id_2 = Commitment::from_witness(builder, native_key->id_2); - this->id_3 = Commitment::from_witness(builder, native_key->id_3); - this->id_4 = Commitment::from_witness(builder, native_key->id_4); - this->table_1 = Commitment::from_witness(builder, native_key->table_1); - this->table_2 = Commitment::from_witness(builder, native_key->table_2); - this->table_3 = Commitment::from_witness(builder, native_key->table_3); - this->table_4 = Commitment::from_witness(builder, native_key->table_4); - this->lagrange_first = Commitment::from_witness(builder, native_key->lagrange_first); - this->lagrange_last = Commitment::from_witness(builder, native_key->lagrange_last); + + // Generate stdlib commitments (biggroup) from the native counterparts + for (auto [commitment, native_commitment] : zip_view(this->get_all(), native_key->get_all())) { + commitment = Commitment::from_witness(builder, native_commitment); + } }; /** @@ -162,43 +140,41 @@ template class UltraRecursiveFlavor_ { */ VerificationKey(CircuitBuilder& builder, std::span elements) { - // deserialize circuit size + using namespace bb::stdlib::field_conversion; + size_t num_frs_read = 0; - size_t num_frs_FF = bb::stdlib::field_conversion::calc_num_bn254_frs(); - size_t num_frs_Comm = bb::stdlib::field_conversion::calc_num_bn254_frs(); - - this->circuit_size = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_FF)) - .get_value()); - num_frs_read += num_frs_FF; - this->num_public_inputs = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_FF)) - .get_value()); - num_frs_read += num_frs_FF; - - this->pub_inputs_offset = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_FF)) - .get_value()); - num_frs_read += num_frs_FF; - - this->contains_recursive_proof = bool(stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_FF)) - .get_value()); - num_frs_read += num_frs_FF; - - for (uint32_t i = 0; i < bb::AGGREGATION_OBJECT_SIZE; ++i) { - this->recursive_proof_public_input_indices[i] = - uint32_t(stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_FF)) - .get_value()); - num_frs_read += num_frs_FF; + + this->circuit_size = uint64_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->num_public_inputs = uint64_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->pub_inputs_offset = uint64_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->contains_recursive_proof = + bool(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + + for (uint32_t& idx : this->recursive_proof_public_input_indices) { + idx = uint32_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); } - for (Commitment& comm : this->get_all()) { - comm = bb::stdlib::field_conversion::convert_from_bn254_frs( - builder, elements.subspan(num_frs_read, num_frs_Comm)); - num_frs_read += num_frs_Comm; + for (Commitment& commitment : this->get_all()) { + commitment = deserialize_from_frs(builder, elements, num_frs_read); + } + } + + /** + * @brief Construct a VerificationKey from a set of corresponding witness indices + * + * @param builder + * @param witness_indices + * @return VerificationKey + */ + static VerificationKey from_witness_indices(CircuitBuilder& builder, + const std::span& witness_indices) + { + std::vector vkey_fields; + vkey_fields.reserve(witness_indices.size()); + for (const auto& idx : witness_indices) { + vkey_fields.emplace_back(FF::from_witness_index(&builder, idx)); } + return VerificationKey(builder, vkey_fields); } }; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.cpp new file mode 100644 index 00000000000..fad82be3874 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.cpp @@ -0,0 +1,3 @@ +#include "sumcheck.hpp" + +// Hack to make the module compile. diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 10e580cf810..fccab56b551 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -1,9 +1,9 @@ #pragma once #include "barretenberg/plonk_honk_shared/library/grand_product_delta.hpp" #include "barretenberg/polynomials/polynomial_arithmetic.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" #include "barretenberg/sumcheck/sumcheck_output.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" #include "sumcheck_round.hpp" namespace bb { @@ -123,7 +123,6 @@ template class SumcheckProver { using ClaimedEvaluations = typename Flavor::AllValues; using Transcript = typename Flavor::Transcript; - using DeciderPK = DeciderProvingKey_; using RelationSeparator = typename Flavor::RelationSeparator; /** * @brief The total algebraic degree of the Sumcheck relation \f$ F \f$ as a polynomial in Prover Polynomials @@ -178,15 +177,6 @@ template class SumcheckProver { , round(multivariate_n) , partially_evaluated_polynomials(multivariate_n){}; - /** - * @brief Compute round univariate, place it in transcript, compute challenge, partially evaluate. Repeat - * until final round, then get full evaluations of prover polynomials, and place them in transcript. - */ - SumcheckOutput prove(std::shared_ptr key) - { - return prove(key->proving_key.polynomials, key->relation_parameters, key->alphas, key->gate_challenges); - }; - /** * @brief Compute round univariate, place it in transcript, compute challenge, partially evaluate. Repeat * until final round, then get full evaluations of prover polynomials, and place them in transcript. @@ -334,7 +324,7 @@ template class SumcheckProver { // after the first round, operate in place on partially_evaluated_polynomials parallel_for(poly_view.size(), [&](size_t j) { for (size_t i = 0; i < round_size; i += 2) { - pep_view[j][i >> 1] = poly_view[j][i] + round_challenge * (poly_view[j][i + 1] - poly_view[j][i]); + pep_view[j].at(i >> 1) = poly_view[j][i] + round_challenge * (poly_view[j][i + 1] - poly_view[j][i]); } }); }; @@ -349,7 +339,8 @@ template class SumcheckProver { // after the first round, operate in place on partially_evaluated_polynomials parallel_for(polynomials.size(), [&](size_t j) { for (size_t i = 0; i < round_size; i += 2) { - pep_view[j][i >> 1] = polynomials[j][i] + round_challenge * (polynomials[j][i + 1] - polynomials[j][i]); + pep_view[j].at(i >> 1) = + polynomials[j][i] + round_challenge * (polynomials[j][i + 1] - polynomials[j][i]); } }); }; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp index cc38be1383a..eac46840fe8 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp @@ -26,7 +26,7 @@ template class SumcheckTests : public ::testing::Test { Polynomial random_poly(size_t size) { auto poly = bb::Polynomial(size); - for (auto& coeff : poly) { + for (auto& coeff : poly.coeffs()) { coeff = FF::random_element(); } return poly; diff --git a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp index 8220d57c681..06f69bdcb13 100644 --- a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp @@ -1,8 +1,8 @@ #pragma once - // #define LOG_CHALLENGES // #define LOG_INTERACTIONS +#include "barretenberg/common/debug_log.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/ecc/curves/bn254/g1.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" @@ -51,6 +51,19 @@ class TranscriptManifest { { manifest[round].challenge_label = { labels... }; } + template + void add_challenge(size_t round, std::array labels) + { + auto call_add_challenge = [&] { + auto call_fn_with_expanded_parameters = + [&]([[maybe_unused]] std::index_sequence) { + return add_challenge(round, std::get(labels)...); + }; + return call_fn_with_expanded_parameters(std::make_index_sequence()); + }; + call_add_challenge(); + } + void add_entry(size_t round, const std::string& element_label, size_t element_size) { manifest[round].entries.emplace_back(element_label, element_size); @@ -71,6 +84,25 @@ struct NativeTranscriptParams { { return bb::field_conversion::convert_challenge(challenge); } + /** + * @brief Split a challenge field element into two half-width challenges + * @details `lo` is 128 bits and `hi` is 126 bits. + * This should provide significantly more than our security parameter bound: 100 bits + * + * @param challenge + * @return std::array + */ + static inline std::array split_challenge(const Fr& challenge) + { + // match the parameter used in stdlib, which is derived from cycle_scalar (is 128) + static constexpr size_t LO_BITS = Fr::Params::MAX_BITS_PER_ENDOMORPHISM_SCALAR; + static constexpr size_t HI_BITS = Fr::modulus.get_msb() + 1 - LO_BITS; + + auto converted = static_cast(challenge); + uint256_t lo = converted.slice(0, LO_BITS); + uint256_t hi = converted.slice(LO_BITS, LO_BITS + HI_BITS); + return std::array{ Fr(lo), Fr(hi) }; + } template static constexpr size_t calc_num_bn254_frs() { return bb::field_conversion::calc_num_bn254_frs(); @@ -128,8 +160,10 @@ template class BaseTranscript { * to the current challenge buffer to set up next function call. * @return std::array */ - [[nodiscard]] Fr get_next_challenge_buffer() + [[nodiscard]] std::array get_next_duplex_challenge_buffer(size_t num_challenges) { + // challenges need at least 110 bits in them to match the presumed security parameter of the BN254 curve. + ASSERT(num_challenges <= 2); // Prevent challenge generation if this is the first challenge we're generating, // AND nothing was sent by the prover. if (is_first_challenge) { @@ -138,8 +172,8 @@ template class BaseTranscript { // concatenate the previous challenge (if this is not the first challenge) with the current round data. // TODO(Adrian): Do we want to use a domain separator as the initial challenge buffer? - // We could be cheeky and use the hash of the manifest as domain separator, which would prevent us from having - // to domain separate all the data. (See https://safe-hash.dev) + // We could be cheeky and use the hash of the manifest as domain separator, which would prevent us from + // having to domain separate all the data. (See https://safe-hash.dev) std::vector full_buffer; if (!is_first_challenge) { // if not the first challenge, we can use the previous_challenge @@ -156,14 +190,15 @@ template class BaseTranscript { current_round_data.clear(); // clear the round data buffer since it has been used } - // Hash the full buffer with poseidon2, which is believed to be a collision resistant hash function and a random - // oracle, removing the need to pre-hash to compress and then hash with a random oracle, as we previously did - // with Pedersen and Blake3s. + // Hash the full buffer with poseidon2, which is believed to be a collision resistant hash function and a + // random oracle, removing the need to pre-hash to compress and then hash with a random oracle, as we + // previously did with Pedersen and Blake3s. Fr new_challenge = TranscriptParams::hash(full_buffer); - + std::array new_challenges = TranscriptParams::split_challenge(new_challenge); // update previous challenge buffer for next time we call this function + ASSERT(num_challenges <= 2); previous_challenge = new_challenge; - return new_challenge; + return new_challenges; }; protected: @@ -241,12 +276,10 @@ template class BaseTranscript { } /** - * @brief After all the prover messages have been sent, finalize the round by hashing all the data and then create - * the number of requested challenges. + * @brief After all the prover messages have been sent, finalize the round by hashing all the data and then + * create the number of requested challenges. * @details Challenges are generated by iteratively hashing over the previous challenge, using * get_next_challenge_buffer(). - * TODO(#741): Optimizations for this function include generalizing type of hash, splitting hashes into - * multiple challenges. * * @param labels human-readable names for the challenges for the manifest * @return std::array challenges for this round. @@ -265,20 +298,15 @@ template class BaseTranscript { std::array challenges{}; // Generate the challenges by iteratively hashing over the previous challenge. - for (size_t i = 0; i < num_challenges; i++) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/741): Optimize this by truncating hash to 128 - // bits or by splitting hash into 2 challenges. - /* - auto next_challenge_buffer = get_next_challenge_buffer(); // get next challenge buffer - Fr field_element_buffer = next_challenge_buffer; - // copy half of the hash to lower 128 bits of challenge Note: because of how read() from buffers to fields - works (in field_declarations.hpp), we use the later half of the buffer - // std::copy_n(next_challenge_buffer.begin(), - // HASH_OUTPUT_SIZE / 2, - // field_element_buffer.begin() + HASH_OUTPUT_SIZE / 2); - */ - auto challenge_buffer = get_next_challenge_buffer(); - challenges[i] = TranscriptParams::template convert_challenge(challenge_buffer); + for (size_t i = 0; i < num_challenges / 2; i += 1) { + auto challenge_buffer = get_next_duplex_challenge_buffer(2); + challenges[2 * i] = TranscriptParams::template convert_challenge(challenge_buffer[0]); + challenges[2 * i + 1] = TranscriptParams::template convert_challenge(challenge_buffer[1]); + } + if ((num_challenges & 1) == 1) { + auto challenge_buffer = get_next_duplex_challenge_buffer(1); + challenges[num_challenges - 1] = + TranscriptParams::template convert_challenge(challenge_buffer[0]); } // Prepare for next round. @@ -287,6 +315,28 @@ template class BaseTranscript { return challenges; } + /** + * @brief After all the prover messages have been sent, finalize the round by hashing all the data and then create + * the number of requested challenges. + * @details Challenges are generated by iteratively hashing over the previous challenge, using + * get_next_challenge_buffer(). + * + * @param array of labels human-readable names for the challenges for the manifest + * @return std::array challenges for this round. + */ + template + std::array get_challenges(const std::array labels) + { + auto call_get_challenges = [&] { + auto call_fn_with_expanded_parameters = + [&]([[maybe_unused]] std::index_sequence) { + return get_challenges(std::get(labels)...); + }; + return call_fn_with_expanded_parameters(std::make_index_sequence()); + }; + return call_get_challenges(); + } + /** * @brief Adds a prover message to the transcript, only intended to be used by the prover. * @@ -302,6 +352,8 @@ template class BaseTranscript { */ template void send_to_verifier(const std::string& label, const T& element) { + DEBUG_LOG(label, element); + // TODO(Adrian): Ensure that serialization of affine elements (including point at infinity) is consistent. // TODO(Adrian): Consider restricting serialization (via concepts) to types T for which sizeof(T) reliably // returns the size of T in frs. (E.g. this is true for std::array but not for std::vector). @@ -318,7 +370,8 @@ template class BaseTranscript { } /** - * @brief Reads the next element of type `T` from the transcript, with a predefined label, only used by verifier. + * @brief Reads the next element of type `T` from the transcript, with a predefined label, only used by + * verifier. * * @param label Human readable name for the challenge. * @return deserialized element of type T @@ -334,6 +387,7 @@ template class BaseTranscript { BaseTranscript::consume_prover_element_frs(label, element_frs); auto element = TranscriptParams::template convert_from_bn254_frs(element_frs); + DEBUG_LOG(label, element); #ifdef LOG_INTERACTIONS if constexpr (Loggable) { @@ -344,8 +398,8 @@ template class BaseTranscript { } /** - * @brief For testing: initializes transcript with some arbitrary data so that a challenge can be generated after - * initialization. Only intended to be used by Prover. + * @brief For testing: initializes transcript with some arbitrary data so that a challenge can be generated + * after initialization. Only intended to be used by Prover. * * @return BaseTranscript */ @@ -377,6 +431,7 @@ template class BaseTranscript { #if defined LOG_CHALLENGES || defined LOG_INTERACTIONS info("challenge: ", label, ": ", result); #endif + DEBUG_LOG(label, result); return result; } @@ -452,6 +507,10 @@ struct KeccakTranscriptParams { // verifier for keccak resulting in twice as much hashing return bb::field_conversion::convert_to_bn254_frs(element); } + static inline std::array split_challenge(const Fr& challenge) + { + return NativeTranscriptParams::split_challenge(challenge); + } }; using KeccakTranscript = BaseTranscript; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp index 14336957ea7..8d448a6f829 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -57,18 +57,25 @@ TEST_F(TranslatorRelationCorrectnessTests, Permutation) // Create storage for polynomials ProverPolynomials prover_polynomials; + // ensure we can shift these + for (Polynomial& prover_poly : prover_polynomials.get_to_be_shifted()) { + prover_poly = Polynomial::shiftable(full_circuit_size); + } + for (Polynomial& prover_poly : prover_polynomials.get_all()) { - prover_poly = Polynomial{ full_circuit_size }; + if (prover_poly.is_empty()) { + prover_poly = Polynomial{ full_circuit_size }; + } } // Fill in lagrange polynomials used in the permutation relation - prover_polynomials.lagrange_first[0] = 1; - prover_polynomials.lagrange_last[full_circuit_size - 1] = 1; + prover_polynomials.lagrange_first.at(0) = 1; + prover_polynomials.lagrange_last.at(full_circuit_size - 1) = 1; // Put random values in all the non-concatenated constraint polynomials used to range constrain the values auto fill_polynomial_with_random_14_bit_values = [&](auto& polynomial) { - for (size_t i = 0; i < mini_circuit_size; i++) { - polynomial[i] = engine.get_random_uint16() & ((1 << Flavor::MICRO_LIMB_BITS) - 1); + for (size_t i = polynomial.start_index(); i < mini_circuit_size; i++) { + polynomial.at(i) = engine.get_random_uint16() & ((1 << Flavor::MICRO_LIMB_BITS) - 1); } }; fill_polynomial_with_random_14_bit_values(prover_polynomials.p_x_low_limbs_range_constraint_0); @@ -172,24 +179,29 @@ TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) ProverPolynomials prover_polynomials; // Allocate polynomials - for (Polynomial& polynomial : prover_polynomials.get_all()) { - polynomial = Polynomial{ circuit_size }; + for (Polynomial& prover_poly : prover_polynomials.get_to_be_shifted()) { + prover_poly = Polynomial::shiftable(circuit_size); + } + for (Polynomial& prover_poly : prover_polynomials.get_all()) { + if (prover_poly.is_empty()) { + prover_poly = Polynomial{ circuit_size }; + } } // Construct lagrange polynomials that are needed for Translator's DeltaRangeConstraint Relation - prover_polynomials.lagrange_first[0] = 1; - prover_polynomials.lagrange_last[circuit_size - 1] = 1; + prover_polynomials.lagrange_first.at(0) = 0; + prover_polynomials.lagrange_last.at(circuit_size - 1) = 1; // Create a vector and fill with necessary steps for the DeltaRangeConstraint relation auto sorted_elements_count = (max_value / sort_step) + 1; - std::vector vector_for_sorting(circuit_size); + std::vector vector_for_sorting(prover_polynomials.ordered_range_constraints_0.size()); for (size_t i = 0; i < sorted_elements_count - 1; i++) { vector_for_sorting[i] = i * sort_step; } vector_for_sorting[sorted_elements_count - 1] = max_value; // Add random values to fill the leftover space - for (size_t i = sorted_elements_count; i < circuit_size; i++) { + for (size_t i = sorted_elements_count; i < vector_for_sorting.size(); i++) { vector_for_sorting[i] = engine.get_random_uint16() & ((1 << Flavor::MICRO_LIMB_BITS) - 1); } @@ -206,15 +218,15 @@ TEST_F(TranslatorRelationCorrectnessTests, DeltaRangeConstraint) // Copy values, transforming them into Finite Field elements std::transform(vector_for_sorting.cbegin(), vector_for_sorting.cend(), - prover_polynomials.ordered_range_constraints_0.begin(), + prover_polynomials.ordered_range_constraints_0.coeffs().begin(), [](uint64_t in) { return FF(in); }); // Copy the same polynomial into the 4 other ordered polynomials (they are not the same in an actual proof, but we // only need to check the correctness of the relation and it acts independently on each polynomial) parallel_for(4, [&](size_t i) { - std::copy(prover_polynomials.ordered_range_constraints_0.begin(), - prover_polynomials.ordered_range_constraints_0.end(), - polynomial_pointers[i + 1]->begin()); + std::copy(prover_polynomials.ordered_range_constraints_0.coeffs().begin(), + prover_polynomials.ordered_range_constraints_0.coeffs().end(), + polynomial_pointers[i + 1]->coeffs().begin()); }); // Get shifted polynomials @@ -262,19 +274,23 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) std::vector polynomial_container; std::vector polynomial_ids; for (size_t i = 0; i < polynomial_id_get_all.size(); i++) { - Polynomial temporary_polynomial(circuit_size); // Allocate polynomials - polynomial_container.push_back(temporary_polynomial); + polynomial_container.emplace_back(circuit_size); // Push sequential ids to polynomial ids polynomial_ids.push_back(i); polynomial_id_get_all[i] = polynomial_ids[i]; } // Get ids of shifted polynomials and put them in a set auto shifted_ids = prover_polynomial_ids.get_shifted(); + auto to_be_shifted_ids = prover_polynomial_ids.get_to_be_shifted(); std::unordered_set shifted_id_set; for (auto& id : shifted_ids) { shifted_id_set.emplace(id); } + for (auto& id : to_be_shifted_ids) { + // allow shifting + polynomial_container[id] = Polynomial{ circuit_size - 1, circuit_size, 1 }; + } // Assign to non-shifted prover polynomials auto polynomial_get_all = prover_polynomials.get_all(); for (size_t i = 0; i < polynomial_get_all.size(); i++) { @@ -286,44 +302,45 @@ TEST_F(TranslatorRelationCorrectnessTests, TranslatorExtraRelationsCorrectness) // Assign to shifted prover polynomials using ids for (size_t i = 0; i < shifted_ids.size(); i++) { auto shifted_id = shifted_ids[i]; - auto to_be_shifted_id = prover_polynomial_ids.get_to_be_shifted()[i]; + auto to_be_shifted_id = to_be_shifted_ids[i]; + // Ensure we can shift this polynomial_get_all[shifted_id] = polynomial_container[to_be_shifted_id].shifted(); } // Fill in lagrange even polynomial for (size_t i = 2; i < mini_circuit_size; i += 2) { - prover_polynomials.lagrange_even_in_minicircuit[i] = 1; + prover_polynomials.lagrange_even_in_minicircuit.at(i) = 1; } constexpr size_t NUMBER_OF_POSSIBLE_OPCODES = 6; constexpr std::array possible_opcode_values = { 0, 1, 2, 3, 4, 8 }; // Assign random opcode values for (size_t i = 1; i < mini_circuit_size - 1; i += 2) { - prover_polynomials.op[i] = + prover_polynomials.op.at(i) = possible_opcode_values[static_cast(engine.get_random_uint8() % NUMBER_OF_POSSIBLE_OPCODES)]; } // Initialize used lagrange polynomials - prover_polynomials.lagrange_second[1] = 1; - prover_polynomials.lagrange_second_to_last_in_minicircuit[mini_circuit_size - 2] = 1; + prover_polynomials.lagrange_second.at(1) = 1; + prover_polynomials.lagrange_second_to_last_in_minicircuit.at(mini_circuit_size - 2) = 1; // Put random values in accumulator binary limbs (values should be preserved across even->next odd shift) for (size_t i = 2; i < mini_circuit_size - 2; i += 2) { - prover_polynomials.accumulators_binary_limbs_0[i] = FF ::random_element(); - prover_polynomials.accumulators_binary_limbs_1[i] = FF ::random_element(); - prover_polynomials.accumulators_binary_limbs_2[i] = FF ::random_element(); - prover_polynomials.accumulators_binary_limbs_3[i] = FF ::random_element(); - prover_polynomials.accumulators_binary_limbs_0[i + 1] = prover_polynomials.accumulators_binary_limbs_0[i]; - prover_polynomials.accumulators_binary_limbs_1[i + 1] = prover_polynomials.accumulators_binary_limbs_1[i]; - prover_polynomials.accumulators_binary_limbs_2[i + 1] = prover_polynomials.accumulators_binary_limbs_2[i]; - prover_polynomials.accumulators_binary_limbs_3[i + 1] = prover_polynomials.accumulators_binary_limbs_3[i]; + prover_polynomials.accumulators_binary_limbs_0.at(i) = FF ::random_element(); + prover_polynomials.accumulators_binary_limbs_1.at(i) = FF ::random_element(); + prover_polynomials.accumulators_binary_limbs_2.at(i) = FF ::random_element(); + prover_polynomials.accumulators_binary_limbs_3.at(i) = FF ::random_element(); + prover_polynomials.accumulators_binary_limbs_0.at(i + 1) = prover_polynomials.accumulators_binary_limbs_0[i]; + prover_polynomials.accumulators_binary_limbs_2.at(i + 1) = prover_polynomials.accumulators_binary_limbs_2[i]; + prover_polynomials.accumulators_binary_limbs_1.at(i + 1) = prover_polynomials.accumulators_binary_limbs_1[i]; + prover_polynomials.accumulators_binary_limbs_3.at(i + 1) = prover_polynomials.accumulators_binary_limbs_3[i]; } // The values of accumulator binary limbs at index 1 should equal the accumulated result from relation parameters - prover_polynomials.accumulators_binary_limbs_0[1] = params.accumulated_result[0]; - prover_polynomials.accumulators_binary_limbs_1[1] = params.accumulated_result[1]; - prover_polynomials.accumulators_binary_limbs_2[1] = params.accumulated_result[2]; - prover_polynomials.accumulators_binary_limbs_3[1] = params.accumulated_result[3]; + prover_polynomials.accumulators_binary_limbs_0.at(1) = params.accumulated_result[0]; + prover_polynomials.accumulators_binary_limbs_1.at(1) = params.accumulated_result[1]; + prover_polynomials.accumulators_binary_limbs_2.at(1) = params.accumulated_result[2]; + prover_polynomials.accumulators_binary_limbs_3.at(1) = params.accumulated_result[3]; using Relations = typename Flavor::Relations; @@ -371,10 +388,15 @@ TEST_F(TranslatorRelationCorrectnessTests, Decomposition) } // Get ids of shifted polynomials and put them in a set auto shifted_ids = prover_polynomial_ids.get_shifted(); + auto to_be_shifted_ids = prover_polynomial_ids.get_to_be_shifted(); std::unordered_set shifted_id_set; for (auto& id : shifted_ids) { shifted_id_set.emplace(id); } + for (auto& id : to_be_shifted_ids) { + // allow shifting + polynomial_container[id] = Polynomial{ circuit_size - 1, circuit_size, 1 }; + } // Assign spans to non-shifted prover polynomials for (size_t i = 0; i < polynomial_get_all.size(); i++) { if (!shifted_id_set.contains(i)) { @@ -385,13 +407,14 @@ TEST_F(TranslatorRelationCorrectnessTests, Decomposition) // Assign shifted spans to shifted prover polynomials using ids for (size_t i = 0; i < shifted_ids.size(); i++) { auto shifted_id = shifted_ids[i]; - auto to_be_shifted_id = prover_polynomial_ids.get_to_be_shifted()[i]; + auto to_be_shifted_id = to_be_shifted_ids[i]; + // Ensure we can shift this polynomial_get_all[shifted_id] = polynomial_container[to_be_shifted_id].shifted(); } // Fill in lagrange odd polynomial (the only non-witness one we are using) for (size_t i = 1; i < mini_circuit_size - 1; i += 2) { - prover_polynomials.lagrange_odd_in_minicircuit[i] = 1; + prover_polynomials.lagrange_odd_in_minicircuit.at(i) = 1; } constexpr size_t NUM_LIMB_BITS = Flavor::CircuitBuilder::NUM_LIMB_BITS; @@ -480,226 +503,231 @@ TEST_F(TranslatorRelationCorrectnessTests, Decomposition) // Put random values in all the non-concatenated constraint polynomials used to range constrain the values for (size_t i = 1; i < mini_circuit_size - 1; i += 2) { // P.x - prover_polynomials.x_lo_y_hi[i] = FF(engine.get_random_uint256() & ((uint256_t(1) << LOW_WIDE_LIMB_WIDTH) - 1)); - prover_polynomials.x_hi_z_1[i] = FF(engine.get_random_uint256() & ((uint256_t(1) << HIGH_WIDE_LIMB_WIDTH) - 1)); + prover_polynomials.x_lo_y_hi.at(i) = + FF(engine.get_random_uint256() & ((uint256_t(1) << LOW_WIDE_LIMB_WIDTH) - 1)); + prover_polynomials.x_hi_z_1.at(i) = + FF(engine.get_random_uint256() & ((uint256_t(1) << HIGH_WIDE_LIMB_WIDTH) - 1)); // P.y - prover_polynomials.y_lo_z_2[i] = FF(engine.get_random_uint256() & ((uint256_t(1) << LOW_WIDE_LIMB_WIDTH) - 1)); - prover_polynomials.x_lo_y_hi[i + 1] = + prover_polynomials.y_lo_z_2.at(i) = + FF(engine.get_random_uint256() & ((uint256_t(1) << LOW_WIDE_LIMB_WIDTH) - 1)); + prover_polynomials.x_lo_y_hi.at(i + 1) = FF(engine.get_random_uint256() & ((uint256_t(1) << HIGH_WIDE_LIMB_WIDTH) - 1)); // z1 and z2 - prover_polynomials.x_hi_z_1[i + 1] = FF(engine.get_random_uint256() & ((uint256_t(1) << Z_LIMB_WIDTH) - 1)); - prover_polynomials.y_lo_z_2[i + 1] = FF(engine.get_random_uint256() & ((uint256_t(1) << Z_LIMB_WIDTH) - 1)); + prover_polynomials.x_hi_z_1.at(i + 1) = FF(engine.get_random_uint256() & ((uint256_t(1) << Z_LIMB_WIDTH) - 1)); + prover_polynomials.y_lo_z_2.at(i + 1) = FF(engine.get_random_uint256() & ((uint256_t(1) << Z_LIMB_WIDTH) - 1)); // Slice P.x into chunks - prover_polynomials.p_x_low_limbs[i] = uint256_t(prover_polynomials.x_lo_y_hi[i]).slice(0, NUM_LIMB_BITS); - prover_polynomials.p_x_low_limbs[i + 1] = - uint256_t(prover_polynomials.x_lo_y_hi[i]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS); - prover_polynomials.p_x_high_limbs[i] = uint256_t(prover_polynomials.x_hi_z_1[i]).slice(0, NUM_LIMB_BITS); - prover_polynomials.p_x_high_limbs[i + 1] = - uint256_t(prover_polynomials.x_hi_z_1[i]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS); + prover_polynomials.p_x_low_limbs.at(i) = uint256_t(prover_polynomials.x_lo_y_hi.at(i)).slice(0, NUM_LIMB_BITS); + prover_polynomials.p_x_low_limbs.at(i + 1) = + uint256_t(prover_polynomials.x_lo_y_hi.at(i)).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS); + prover_polynomials.p_x_high_limbs.at(i) = uint256_t(prover_polynomials.x_hi_z_1[i]).slice(0, NUM_LIMB_BITS); + prover_polynomials.p_x_high_limbs.at(i + 1) = + uint256_t(prover_polynomials.x_hi_z_1.at(i)).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS); // Slice P.y into chunks - prover_polynomials.p_y_low_limbs[i] = uint256_t(prover_polynomials.y_lo_z_2[i]).slice(0, NUM_LIMB_BITS); - prover_polynomials.p_y_low_limbs[i + 1] = + prover_polynomials.p_y_low_limbs.at(i) = uint256_t(prover_polynomials.y_lo_z_2[i]).slice(0, NUM_LIMB_BITS); + prover_polynomials.p_y_low_limbs.at(i + 1) = uint256_t(prover_polynomials.y_lo_z_2[i]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS); - prover_polynomials.p_y_high_limbs[i] = uint256_t(prover_polynomials.x_lo_y_hi[i + 1]).slice(0, NUM_LIMB_BITS); - prover_polynomials.p_y_high_limbs[i + 1] = + prover_polynomials.p_y_high_limbs.at(i) = + uint256_t(prover_polynomials.x_lo_y_hi[i + 1]).slice(0, NUM_LIMB_BITS); + prover_polynomials.p_y_high_limbs.at(i + 1) = uint256_t(prover_polynomials.x_lo_y_hi[i + 1]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS); // Slice z1 and z2 into chunks - prover_polynomials.z_low_limbs[i] = uint256_t(prover_polynomials.x_hi_z_1[i + 1]).slice(0, NUM_LIMB_BITS); - prover_polynomials.z_low_limbs[i + 1] = uint256_t(prover_polynomials.y_lo_z_2[i + 1]).slice(0, NUM_LIMB_BITS); - prover_polynomials.z_high_limbs[i] = + prover_polynomials.z_low_limbs.at(i) = uint256_t(prover_polynomials.x_hi_z_1[i + 1]).slice(0, NUM_LIMB_BITS); + prover_polynomials.z_low_limbs.at(i + 1) = + uint256_t(prover_polynomials.y_lo_z_2[i + 1]).slice(0, NUM_LIMB_BITS); + prover_polynomials.z_high_limbs.at(i) = uint256_t(prover_polynomials.x_hi_z_1[i + 1]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS); - prover_polynomials.z_high_limbs[i + 1] = + prover_polynomials.z_high_limbs.at(i + 1) = uint256_t(prover_polynomials.y_lo_z_2[i + 1]).slice(NUM_LIMB_BITS, 2 * NUM_LIMB_BITS); // Slice accumulator auto tmp = uint256_t(BF::random_element(&engine)); - prover_polynomials.accumulators_binary_limbs_0[i] = tmp.slice(0, NUM_LIMB_BITS); - prover_polynomials.accumulators_binary_limbs_1[i] = tmp.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2); - prover_polynomials.accumulators_binary_limbs_2[i] = tmp.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3); - prover_polynomials.accumulators_binary_limbs_3[i] = tmp.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4); + prover_polynomials.accumulators_binary_limbs_0.at(i) = tmp.slice(0, NUM_LIMB_BITS); + prover_polynomials.accumulators_binary_limbs_1.at(i) = tmp.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2); + prover_polynomials.accumulators_binary_limbs_2.at(i) = tmp.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3); + prover_polynomials.accumulators_binary_limbs_3.at(i) = tmp.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4); // Slice low limbs of P.x into range constraint microlimbs - decompose_standard_limb(prover_polynomials.p_x_low_limbs[i], - prover_polynomials.p_x_low_limbs_range_constraint_0[i], - prover_polynomials.p_x_low_limbs_range_constraint_1[i], - prover_polynomials.p_x_low_limbs_range_constraint_2[i], - prover_polynomials.p_x_low_limbs_range_constraint_3[i], - prover_polynomials.p_x_low_limbs_range_constraint_4[i], - prover_polynomials.p_x_low_limbs_range_constraint_tail[i]); - - decompose_standard_limb(prover_polynomials.p_x_low_limbs[i + 1], - prover_polynomials.p_x_low_limbs_range_constraint_0[i + 1], - prover_polynomials.p_x_low_limbs_range_constraint_1[i + 1], - prover_polynomials.p_x_low_limbs_range_constraint_2[i + 1], - prover_polynomials.p_x_low_limbs_range_constraint_3[i + 1], - prover_polynomials.p_x_low_limbs_range_constraint_4[i + 1], - prover_polynomials.p_x_low_limbs_range_constraint_tail[i + 1]); + decompose_standard_limb(prover_polynomials.p_x_low_limbs.at(i), + prover_polynomials.p_x_low_limbs_range_constraint_0.at(i), + prover_polynomials.p_x_low_limbs_range_constraint_1.at(i), + prover_polynomials.p_x_low_limbs_range_constraint_2.at(i), + prover_polynomials.p_x_low_limbs_range_constraint_3.at(i), + prover_polynomials.p_x_low_limbs_range_constraint_4.at(i), + prover_polynomials.p_x_low_limbs_range_constraint_tail.at(i)); + + decompose_standard_limb(prover_polynomials.p_x_low_limbs.at(i + 1), + prover_polynomials.p_x_low_limbs_range_constraint_0.at(i + 1), + prover_polynomials.p_x_low_limbs_range_constraint_1.at(i + 1), + prover_polynomials.p_x_low_limbs_range_constraint_2.at(i + 1), + prover_polynomials.p_x_low_limbs_range_constraint_3.at(i + 1), + prover_polynomials.p_x_low_limbs_range_constraint_4.at(i + 1), + prover_polynomials.p_x_low_limbs_range_constraint_tail.at(i + 1)); // Slice high limbs of P.x into range constraint microlimbs - decompose_standard_limb(prover_polynomials.p_x_high_limbs[i], - prover_polynomials.p_x_high_limbs_range_constraint_0[i], - prover_polynomials.p_x_high_limbs_range_constraint_1[i], - prover_polynomials.p_x_high_limbs_range_constraint_2[i], - prover_polynomials.p_x_high_limbs_range_constraint_3[i], - prover_polynomials.p_x_high_limbs_range_constraint_4[i], - prover_polynomials.p_x_high_limbs_range_constraint_tail[i]); - - decompose_standard_top_limb(prover_polynomials.p_x_high_limbs[i + 1], - prover_polynomials.p_x_high_limbs_range_constraint_0[i + 1], - prover_polynomials.p_x_high_limbs_range_constraint_1[i + 1], - prover_polynomials.p_x_high_limbs_range_constraint_2[i + 1], - prover_polynomials.p_x_high_limbs_range_constraint_3[i + 1], - prover_polynomials.p_x_high_limbs_range_constraint_4[i + 1]); + decompose_standard_limb(prover_polynomials.p_x_high_limbs.at(i), + prover_polynomials.p_x_high_limbs_range_constraint_0.at(i), + prover_polynomials.p_x_high_limbs_range_constraint_1.at(i), + prover_polynomials.p_x_high_limbs_range_constraint_2.at(i), + prover_polynomials.p_x_high_limbs_range_constraint_3.at(i), + prover_polynomials.p_x_high_limbs_range_constraint_4.at(i), + prover_polynomials.p_x_high_limbs_range_constraint_tail.at(i)); + + decompose_standard_top_limb(prover_polynomials.p_x_high_limbs.at(i + 1), + prover_polynomials.p_x_high_limbs_range_constraint_0.at(i + 1), + prover_polynomials.p_x_high_limbs_range_constraint_1.at(i + 1), + prover_polynomials.p_x_high_limbs_range_constraint_2.at(i + 1), + prover_polynomials.p_x_high_limbs_range_constraint_3.at(i + 1), + prover_polynomials.p_x_high_limbs_range_constraint_4.at(i + 1)); // Slice low limbs of P.y into range constraint microlimbs - decompose_standard_limb(prover_polynomials.p_y_low_limbs[i], - prover_polynomials.p_y_low_limbs_range_constraint_0[i], - prover_polynomials.p_y_low_limbs_range_constraint_1[i], - prover_polynomials.p_y_low_limbs_range_constraint_2[i], - prover_polynomials.p_y_low_limbs_range_constraint_3[i], - prover_polynomials.p_y_low_limbs_range_constraint_4[i], - prover_polynomials.p_y_low_limbs_range_constraint_tail[i]); - - decompose_standard_limb(prover_polynomials.p_y_low_limbs[i + 1], - prover_polynomials.p_y_low_limbs_range_constraint_0[i + 1], - prover_polynomials.p_y_low_limbs_range_constraint_1[i + 1], - prover_polynomials.p_y_low_limbs_range_constraint_2[i + 1], - prover_polynomials.p_y_low_limbs_range_constraint_3[i + 1], - prover_polynomials.p_y_low_limbs_range_constraint_4[i + 1], - prover_polynomials.p_y_low_limbs_range_constraint_tail[i + 1]); + decompose_standard_limb(prover_polynomials.p_y_low_limbs.at(i), + prover_polynomials.p_y_low_limbs_range_constraint_0.at(i), + prover_polynomials.p_y_low_limbs_range_constraint_1.at(i), + prover_polynomials.p_y_low_limbs_range_constraint_2.at(i), + prover_polynomials.p_y_low_limbs_range_constraint_3.at(i), + prover_polynomials.p_y_low_limbs_range_constraint_4.at(i), + prover_polynomials.p_y_low_limbs_range_constraint_tail.at(i)); + + decompose_standard_limb(prover_polynomials.p_y_low_limbs.at(i + 1), + prover_polynomials.p_y_low_limbs_range_constraint_0.at(i + 1), + prover_polynomials.p_y_low_limbs_range_constraint_1.at(i + 1), + prover_polynomials.p_y_low_limbs_range_constraint_2.at(i + 1), + prover_polynomials.p_y_low_limbs_range_constraint_3.at(i + 1), + prover_polynomials.p_y_low_limbs_range_constraint_4.at(i + 1), + prover_polynomials.p_y_low_limbs_range_constraint_tail.at(i + 1)); // Slice high limbs of P.y into range constraint microlimbs - decompose_standard_limb(prover_polynomials.p_y_high_limbs[i], - prover_polynomials.p_y_high_limbs_range_constraint_0[i], - prover_polynomials.p_y_high_limbs_range_constraint_1[i], - prover_polynomials.p_y_high_limbs_range_constraint_2[i], - prover_polynomials.p_y_high_limbs_range_constraint_3[i], - prover_polynomials.p_y_high_limbs_range_constraint_4[i], - prover_polynomials.p_y_high_limbs_range_constraint_tail[i]); - - decompose_standard_top_limb(prover_polynomials.p_y_high_limbs[i + 1], - prover_polynomials.p_y_high_limbs_range_constraint_0[i + 1], - prover_polynomials.p_y_high_limbs_range_constraint_1[i + 1], - prover_polynomials.p_y_high_limbs_range_constraint_2[i + 1], - prover_polynomials.p_y_high_limbs_range_constraint_3[i + 1], - prover_polynomials.p_y_high_limbs_range_constraint_4[i + 1]); + decompose_standard_limb(prover_polynomials.p_y_high_limbs.at(i), + prover_polynomials.p_y_high_limbs_range_constraint_0.at(i), + prover_polynomials.p_y_high_limbs_range_constraint_1.at(i), + prover_polynomials.p_y_high_limbs_range_constraint_2.at(i), + prover_polynomials.p_y_high_limbs_range_constraint_3.at(i), + prover_polynomials.p_y_high_limbs_range_constraint_4.at(i), + prover_polynomials.p_y_high_limbs_range_constraint_tail.at(i)); + + decompose_standard_top_limb(prover_polynomials.p_y_high_limbs.at(i + 1), + prover_polynomials.p_y_high_limbs_range_constraint_0.at(i + 1), + prover_polynomials.p_y_high_limbs_range_constraint_1.at(i + 1), + prover_polynomials.p_y_high_limbs_range_constraint_2.at(i + 1), + prover_polynomials.p_y_high_limbs_range_constraint_3.at(i + 1), + prover_polynomials.p_y_high_limbs_range_constraint_4.at(i + 1)); // Slice low limb of of z1 and z2 into range constraints - decompose_standard_limb(prover_polynomials.z_low_limbs[i], - prover_polynomials.z_low_limbs_range_constraint_0[i], - prover_polynomials.z_low_limbs_range_constraint_1[i], - prover_polynomials.z_low_limbs_range_constraint_2[i], - prover_polynomials.z_low_limbs_range_constraint_3[i], - prover_polynomials.z_low_limbs_range_constraint_4[i], - prover_polynomials.z_low_limbs_range_constraint_tail[i]); - - decompose_standard_limb(prover_polynomials.z_low_limbs[i + 1], - prover_polynomials.z_low_limbs_range_constraint_0[i + 1], - prover_polynomials.z_low_limbs_range_constraint_1[i + 1], - prover_polynomials.z_low_limbs_range_constraint_2[i + 1], - prover_polynomials.z_low_limbs_range_constraint_3[i + 1], - prover_polynomials.z_low_limbs_range_constraint_4[i + 1], - prover_polynomials.z_low_limbs_range_constraint_tail[i + 1]); + decompose_standard_limb(prover_polynomials.z_low_limbs.at(i), + prover_polynomials.z_low_limbs_range_constraint_0.at(i), + prover_polynomials.z_low_limbs_range_constraint_1.at(i), + prover_polynomials.z_low_limbs_range_constraint_2.at(i), + prover_polynomials.z_low_limbs_range_constraint_3.at(i), + prover_polynomials.z_low_limbs_range_constraint_4.at(i), + prover_polynomials.z_low_limbs_range_constraint_tail.at(i)); + + decompose_standard_limb(prover_polynomials.z_low_limbs.at(i + 1), + prover_polynomials.z_low_limbs_range_constraint_0.at(i + 1), + prover_polynomials.z_low_limbs_range_constraint_1.at(i + 1), + prover_polynomials.z_low_limbs_range_constraint_2.at(i + 1), + prover_polynomials.z_low_limbs_range_constraint_3.at(i + 1), + prover_polynomials.z_low_limbs_range_constraint_4.at(i + 1), + prover_polynomials.z_low_limbs_range_constraint_tail.at(i + 1)); // Slice high limb of of z1 and z2 into range constraints - decompose_standard_top_z_limb(prover_polynomials.z_high_limbs[i], - prover_polynomials.z_high_limbs_range_constraint_0[i], - prover_polynomials.z_high_limbs_range_constraint_1[i], - prover_polynomials.z_high_limbs_range_constraint_2[i], - prover_polynomials.z_high_limbs_range_constraint_3[i], - prover_polynomials.z_high_limbs_range_constraint_4[i], - prover_polynomials.z_high_limbs_range_constraint_tail[i]); - - decompose_standard_top_z_limb(prover_polynomials.z_high_limbs[i + 1], - prover_polynomials.z_high_limbs_range_constraint_0[i + 1], - prover_polynomials.z_high_limbs_range_constraint_1[i + 1], - prover_polynomials.z_high_limbs_range_constraint_2[i + 1], - prover_polynomials.z_high_limbs_range_constraint_3[i + 1], - prover_polynomials.z_high_limbs_range_constraint_4[i + 1], - prover_polynomials.z_high_limbs_range_constraint_tail[i + 1]); + decompose_standard_top_z_limb(prover_polynomials.z_high_limbs.at(i), + prover_polynomials.z_high_limbs_range_constraint_0.at(i), + prover_polynomials.z_high_limbs_range_constraint_1.at(i), + prover_polynomials.z_high_limbs_range_constraint_2.at(i), + prover_polynomials.z_high_limbs_range_constraint_3.at(i), + prover_polynomials.z_high_limbs_range_constraint_4.at(i), + prover_polynomials.z_high_limbs_range_constraint_tail.at(i)); + + decompose_standard_top_z_limb(prover_polynomials.z_high_limbs.at(i + 1), + prover_polynomials.z_high_limbs_range_constraint_0.at(i + 1), + prover_polynomials.z_high_limbs_range_constraint_1.at(i + 1), + prover_polynomials.z_high_limbs_range_constraint_2.at(i + 1), + prover_polynomials.z_high_limbs_range_constraint_3.at(i + 1), + prover_polynomials.z_high_limbs_range_constraint_4.at(i + 1), + prover_polynomials.z_high_limbs_range_constraint_tail.at(i + 1)); // Slice accumulator limbs into range constraints - decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_0[i], - prover_polynomials.accumulator_low_limbs_range_constraint_0[i], - prover_polynomials.accumulator_low_limbs_range_constraint_1[i], - prover_polynomials.accumulator_low_limbs_range_constraint_2[i], - prover_polynomials.accumulator_low_limbs_range_constraint_3[i], - prover_polynomials.accumulator_low_limbs_range_constraint_4[i], - prover_polynomials.accumulator_low_limbs_range_constraint_tail[i]); - decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_1[i], - prover_polynomials.accumulator_low_limbs_range_constraint_0[i + 1], - prover_polynomials.accumulator_low_limbs_range_constraint_1[i + 1], - prover_polynomials.accumulator_low_limbs_range_constraint_2[i + 1], - prover_polynomials.accumulator_low_limbs_range_constraint_3[i + 1], - prover_polynomials.accumulator_low_limbs_range_constraint_4[i + 1], - prover_polynomials.accumulator_low_limbs_range_constraint_tail[i + 1]); - - decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_2[i], - prover_polynomials.accumulator_high_limbs_range_constraint_0[i], - prover_polynomials.accumulator_high_limbs_range_constraint_1[i], - prover_polynomials.accumulator_high_limbs_range_constraint_2[i], - prover_polynomials.accumulator_high_limbs_range_constraint_3[i], - prover_polynomials.accumulator_high_limbs_range_constraint_4[i], - prover_polynomials.accumulator_high_limbs_range_constraint_tail[i]); - decompose_standard_top_limb(prover_polynomials.accumulators_binary_limbs_3[i], - prover_polynomials.accumulator_high_limbs_range_constraint_0[i + 1], - prover_polynomials.accumulator_high_limbs_range_constraint_1[i + 1], - prover_polynomials.accumulator_high_limbs_range_constraint_2[i + 1], - prover_polynomials.accumulator_high_limbs_range_constraint_3[i + 1], - prover_polynomials.accumulator_high_limbs_range_constraint_4[i + 1]); + decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_0.at(i), + prover_polynomials.accumulator_low_limbs_range_constraint_0.at(i), + prover_polynomials.accumulator_low_limbs_range_constraint_1.at(i), + prover_polynomials.accumulator_low_limbs_range_constraint_2.at(i), + prover_polynomials.accumulator_low_limbs_range_constraint_3.at(i), + prover_polynomials.accumulator_low_limbs_range_constraint_4.at(i), + prover_polynomials.accumulator_low_limbs_range_constraint_tail.at(i)); + decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_1.at(i), + prover_polynomials.accumulator_low_limbs_range_constraint_0.at(i + 1), + prover_polynomials.accumulator_low_limbs_range_constraint_1.at(i + 1), + prover_polynomials.accumulator_low_limbs_range_constraint_2.at(i + 1), + prover_polynomials.accumulator_low_limbs_range_constraint_3.at(i + 1), + prover_polynomials.accumulator_low_limbs_range_constraint_4.at(i + 1), + prover_polynomials.accumulator_low_limbs_range_constraint_tail.at(i + 1)); + + decompose_standard_limb(prover_polynomials.accumulators_binary_limbs_2.at(i), + prover_polynomials.accumulator_high_limbs_range_constraint_0.at(i), + prover_polynomials.accumulator_high_limbs_range_constraint_1.at(i), + prover_polynomials.accumulator_high_limbs_range_constraint_2.at(i), + prover_polynomials.accumulator_high_limbs_range_constraint_3.at(i), + prover_polynomials.accumulator_high_limbs_range_constraint_4.at(i), + prover_polynomials.accumulator_high_limbs_range_constraint_tail.at(i)); + decompose_standard_top_limb(prover_polynomials.accumulators_binary_limbs_3.at(i), + prover_polynomials.accumulator_high_limbs_range_constraint_0.at(i + 1), + prover_polynomials.accumulator_high_limbs_range_constraint_1.at(i + 1), + prover_polynomials.accumulator_high_limbs_range_constraint_2.at(i + 1), + prover_polynomials.accumulator_high_limbs_range_constraint_3.at(i + 1), + prover_polynomials.accumulator_high_limbs_range_constraint_4.at(i + 1)); // Slice quotient limbs into range constraints - decompose_standard_limb(prover_polynomials.quotient_low_binary_limbs[i], - prover_polynomials.quotient_low_limbs_range_constraint_0[i], - prover_polynomials.quotient_low_limbs_range_constraint_1[i], - prover_polynomials.quotient_low_limbs_range_constraint_2[i], - prover_polynomials.quotient_low_limbs_range_constraint_3[i], - prover_polynomials.quotient_low_limbs_range_constraint_4[i], - prover_polynomials.quotient_low_limbs_range_constraint_tail[i]); - decompose_standard_limb(prover_polynomials.quotient_low_binary_limbs_shift[i], - prover_polynomials.quotient_low_limbs_range_constraint_0[i + 1], - prover_polynomials.quotient_low_limbs_range_constraint_1[i + 1], - prover_polynomials.quotient_low_limbs_range_constraint_2[i + 1], - prover_polynomials.quotient_low_limbs_range_constraint_3[i + 1], - prover_polynomials.quotient_low_limbs_range_constraint_4[i + 1], - prover_polynomials.quotient_low_limbs_range_constraint_tail[i + 1]); - - decompose_standard_limb(prover_polynomials.quotient_high_binary_limbs[i], - prover_polynomials.quotient_high_limbs_range_constraint_0[i], - prover_polynomials.quotient_high_limbs_range_constraint_1[i], - prover_polynomials.quotient_high_limbs_range_constraint_2[i], - prover_polynomials.quotient_high_limbs_range_constraint_3[i], - prover_polynomials.quotient_high_limbs_range_constraint_4[i], - prover_polynomials.quotient_high_limbs_range_constraint_tail[i]); - - decompose_top_quotient_limb(prover_polynomials.quotient_high_binary_limbs_shift[i], - prover_polynomials.quotient_high_limbs_range_constraint_0[i + 1], - prover_polynomials.quotient_high_limbs_range_constraint_1[i + 1], - prover_polynomials.quotient_high_limbs_range_constraint_2[i + 1], - prover_polynomials.quotient_high_limbs_range_constraint_3[i + 1], - prover_polynomials.quotient_high_limbs_range_constraint_4[i + 1]); + decompose_standard_limb(prover_polynomials.quotient_low_binary_limbs.at(i), + prover_polynomials.quotient_low_limbs_range_constraint_0.at(i), + prover_polynomials.quotient_low_limbs_range_constraint_1.at(i), + prover_polynomials.quotient_low_limbs_range_constraint_2.at(i), + prover_polynomials.quotient_low_limbs_range_constraint_3.at(i), + prover_polynomials.quotient_low_limbs_range_constraint_4.at(i), + prover_polynomials.quotient_low_limbs_range_constraint_tail.at(i)); + decompose_standard_limb(prover_polynomials.quotient_low_binary_limbs_shift.at(i), + prover_polynomials.quotient_low_limbs_range_constraint_0.at(i + 1), + prover_polynomials.quotient_low_limbs_range_constraint_1.at(i + 1), + prover_polynomials.quotient_low_limbs_range_constraint_2.at(i + 1), + prover_polynomials.quotient_low_limbs_range_constraint_3.at(i + 1), + prover_polynomials.quotient_low_limbs_range_constraint_4.at(i + 1), + prover_polynomials.quotient_low_limbs_range_constraint_tail.at(i + 1)); + + decompose_standard_limb(prover_polynomials.quotient_high_binary_limbs.at(i), + prover_polynomials.quotient_high_limbs_range_constraint_0.at(i), + prover_polynomials.quotient_high_limbs_range_constraint_1.at(i), + prover_polynomials.quotient_high_limbs_range_constraint_2.at(i), + prover_polynomials.quotient_high_limbs_range_constraint_3.at(i), + prover_polynomials.quotient_high_limbs_range_constraint_4.at(i), + prover_polynomials.quotient_high_limbs_range_constraint_tail.at(i)); + + decompose_top_quotient_limb(prover_polynomials.quotient_high_binary_limbs_shift.at(i), + prover_polynomials.quotient_high_limbs_range_constraint_0.at(i + 1), + prover_polynomials.quotient_high_limbs_range_constraint_1.at(i + 1), + prover_polynomials.quotient_high_limbs_range_constraint_2.at(i + 1), + prover_polynomials.quotient_high_limbs_range_constraint_3.at(i + 1), + prover_polynomials.quotient_high_limbs_range_constraint_4.at(i + 1)); // Decompose wide relation limbs into range constraints - decompose_relation_limb(prover_polynomials.relation_wide_limbs[i], - prover_polynomials.relation_wide_limbs_range_constraint_0[i], - prover_polynomials.relation_wide_limbs_range_constraint_1[i], - prover_polynomials.relation_wide_limbs_range_constraint_2[i], - prover_polynomials.relation_wide_limbs_range_constraint_3[i], - prover_polynomials.p_x_high_limbs_range_constraint_tail[i + 1], - prover_polynomials.accumulator_high_limbs_range_constraint_tail[i + 1]); - - decompose_relation_limb(prover_polynomials.relation_wide_limbs[i + 1], - prover_polynomials.relation_wide_limbs_range_constraint_0[i + 1], - prover_polynomials.relation_wide_limbs_range_constraint_1[i + 1], - prover_polynomials.relation_wide_limbs_range_constraint_2[i + 1], - prover_polynomials.relation_wide_limbs_range_constraint_3[i + 1], - prover_polynomials.p_y_high_limbs_range_constraint_tail[i + 1], - prover_polynomials.quotient_high_limbs_range_constraint_tail[i + 1]); + decompose_relation_limb(prover_polynomials.relation_wide_limbs.at(i), + prover_polynomials.relation_wide_limbs_range_constraint_0.at(i), + prover_polynomials.relation_wide_limbs_range_constraint_1.at(i), + prover_polynomials.relation_wide_limbs_range_constraint_2.at(i), + prover_polynomials.relation_wide_limbs_range_constraint_3.at(i), + prover_polynomials.p_x_high_limbs_range_constraint_tail.at(i + 1), + prover_polynomials.accumulator_high_limbs_range_constraint_tail.at(i + 1)); + + decompose_relation_limb(prover_polynomials.relation_wide_limbs.at(i + 1), + prover_polynomials.relation_wide_limbs_range_constraint_0.at(i + 1), + prover_polynomials.relation_wide_limbs_range_constraint_1.at(i + 1), + prover_polynomials.relation_wide_limbs_range_constraint_2.at(i + 1), + prover_polynomials.relation_wide_limbs_range_constraint_3.at(i + 1), + prover_polynomials.p_y_high_limbs_range_constraint_tail.at(i + 1), + prover_polynomials.quotient_high_limbs_range_constraint_tail.at(i + 1)); } using Relations = Flavor::Relations; @@ -758,11 +786,11 @@ TEST_F(TranslatorRelationCorrectnessTests, NonNative) for (size_t i = 0; i < 4 /*Number of powers of v that we need {1,2,3,4}*/; i++) { v_power *= batching_challenge_v; auto uint_v_power = uint256_t(v_power); - params.batching_challenge_v[i] = { uint_v_power.slice(0, NUM_LIMB_BITS), - uint_v_power.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), - uint_v_power.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), - uint_v_power.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), - uint_v_power }; + params.batching_challenge_v.at(i) = { uint_v_power.slice(0, NUM_LIMB_BITS), + uint_v_power.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2), + uint_v_power.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3), + uint_v_power.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4), + uint_v_power }; } auto uint_input_x = uint256_t(evaluation_input_x); params.evaluation_input_x = { uint_input_x.slice(0, NUM_LIMB_BITS), @@ -789,10 +817,15 @@ TEST_F(TranslatorRelationCorrectnessTests, NonNative) } // Get ids of shifted polynomials and put them in a set auto shifted_ids = prover_polynomial_ids.get_shifted(); + auto to_be_shifted_ids = prover_polynomial_ids.get_to_be_shifted(); std::unordered_set shifted_id_set; for (auto& id : shifted_ids) { shifted_id_set.emplace(id); } + for (auto& id : to_be_shifted_ids) { + // allow shifting + polynomial_container[id] = Polynomial{ circuit_size - 1, circuit_size, 1 }; + } // Assign to non-shifted prover polynomials for (size_t i = 0; i < polynomial_get_all.size(); i++) { if (!shifted_id_set.contains(i)) { @@ -803,44 +836,45 @@ TEST_F(TranslatorRelationCorrectnessTests, NonNative) // Assign to shifted prover polynomials using ids for (size_t i = 0; i < shifted_ids.size(); i++) { auto shifted_id = shifted_ids[i]; - auto to_be_shifted_id = prover_polynomial_ids.get_to_be_shifted()[i]; + auto to_be_shifted_id = to_be_shifted_ids[i]; + // Ensure we can shift this polynomial_get_all[shifted_id] = polynomial_container[to_be_shifted_id].shifted(); } // Copy values of wires used in the non-native field relation from the circuit builder for (size_t i = 1; i < circuit_builder.get_num_gates(); i++) { - prover_polynomials.op[i] = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.OP][i]); - prover_polynomials.p_x_low_limbs[i] = + prover_polynomials.op.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.OP][i]); + prover_polynomials.p_x_low_limbs.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_LOW_LIMBS][i]); - prover_polynomials.p_x_high_limbs[i] = + prover_polynomials.p_x_high_limbs.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_X_HIGH_LIMBS][i]); - prover_polynomials.p_y_low_limbs[i] = + prover_polynomials.p_y_low_limbs.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_LOW_LIMBS][i]); - prover_polynomials.p_y_high_limbs[i] = + prover_polynomials.p_y_high_limbs.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.P_Y_HIGH_LIMBS][i]); - prover_polynomials.z_low_limbs[i] = + prover_polynomials.z_low_limbs.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_LOW_LIMBS][i]); - prover_polynomials.z_high_limbs[i] = + prover_polynomials.z_high_limbs.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.Z_HIGH_LIMBS][i]); - prover_polynomials.accumulators_binary_limbs_0[i] = + prover_polynomials.accumulators_binary_limbs_0.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_0][i]); - prover_polynomials.accumulators_binary_limbs_1[i] = + prover_polynomials.accumulators_binary_limbs_1.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_1][i]); - prover_polynomials.accumulators_binary_limbs_2[i] = + prover_polynomials.accumulators_binary_limbs_2.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_2][i]); - prover_polynomials.accumulators_binary_limbs_3[i] = + prover_polynomials.accumulators_binary_limbs_3.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.ACCUMULATORS_BINARY_LIMBS_3][i]); - prover_polynomials.quotient_low_binary_limbs[i] = + prover_polynomials.quotient_low_binary_limbs.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_LOW_BINARY_LIMBS][i]); - prover_polynomials.quotient_high_binary_limbs[i] = + prover_polynomials.quotient_high_binary_limbs.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.QUOTIENT_HIGH_BINARY_LIMBS][i]); - prover_polynomials.relation_wide_limbs[i] = + prover_polynomials.relation_wide_limbs.at(i) = circuit_builder.get_variable(circuit_builder.wires[circuit_builder.RELATION_WIDE_LIMBS][i]); } // Fill in lagrange odd polynomial for (size_t i = 1; i < mini_circuit_size - 1; i += 2) { - prover_polynomials.lagrange_odd_in_minicircuit[i] = 1; + prover_polynomials.lagrange_odd_in_minicircuit.at(i) = 1; } using Relations = Flavor::Relations; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index b1e717caff8..205d0dd9853 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -137,11 +137,11 @@ class TranslatorFlavor { const size_t mini_circuit_dyadic_size = compute_mini_circuit_dyadic_size(builder); for (size_t i = 1; i < mini_circuit_dyadic_size - 1; i += 2) { - this->lagrange_odd_in_minicircuit[i] = 1; - this->lagrange_even_in_minicircuit[i + 1] = 1; + this->lagrange_odd_in_minicircuit.at(i) = 1; + this->lagrange_even_in_minicircuit.at(i + 1) = 1; } - this->lagrange_second[1] = 1; - this->lagrange_second_to_last_in_minicircuit[mini_circuit_dyadic_size - 2] = 1; + this->lagrange_second.at(1) = 1; + this->lagrange_second_to_last_in_minicircuit.at(mini_circuit_dyadic_size - 2) = 1; } /** @@ -181,7 +181,7 @@ class TranslatorFlavor { // TODO(#756): can be parallelized further. This will use at most 5 threads auto fill_with_shift = [&](size_t shift) { for (size_t i = 0; i < sorted_elements_count; i++) { - extra_range_constraint_numerator[shift + i * (NUM_CONCATENATED_WIRES + 1)] = sorted_elements[i]; + extra_range_constraint_numerator.at(shift + i * (NUM_CONCATENATED_WIRES + 1)) = sorted_elements[i]; } }; // Fill polynomials with a sequence, where each element is repeated NUM_CONCATENATED_WIRES+1 times @@ -786,8 +786,16 @@ class TranslatorFlavor { // Constructor to init all unshifted polys to the zero polynomial and set the shifted poly data ProverPolynomials(size_t circuit_size) { + for (auto& poly : get_to_be_shifted()) { + poly = Polynomial{ /*memory size*/ circuit_size - 1, + /*largest possible index*/ circuit_size, + /* offset */ 1 }; + } for (auto& poly : get_unshifted()) { - poly = Polynomial{ circuit_size }; + if (poly.is_empty()) { + // Not set above + poly = Polynomial{ /*memory size*/ circuit_size, /*largest possible index*/ circuit_size }; + } } set_shifted(); } @@ -803,6 +811,7 @@ class TranslatorFlavor { */ [[nodiscard]] AllValues get_row(size_t row_idx) const { + BB_OP_COUNT_TIME(); AllValues result; for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) { result_field = polynomial[row_idx]; @@ -840,8 +849,8 @@ class TranslatorFlavor { , polynomials(this->circuit_size) { // First and last lagrange polynomials (in the full circuit size) - polynomials.lagrange_first[0] = 1; - polynomials.lagrange_last[circuit_size - 1] = 1; + polynomials.lagrange_first.at(0) = 1; + polynomials.lagrange_last.at(circuit_size - 1) = 1; // Compute polynomials with odd and even indices set to 1 up to the minicircuit margin + lagrange // polynomials at second and second to last indices in the minicircuit diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index 2bc903a4592..b172d003f77 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -36,7 +36,11 @@ void TranslatorProver::compute_witness(CircuitBuilder& circuit_builder) for (auto [wire_poly, wire] : zip_view(key->polynomials.get_wires(), circuit_builder.wires)) { parallel_for_range(circuit_builder.num_gates, [&](size_t start, size_t end) { for (size_t i = start; i < end; i++) { - wire_poly[i] = circuit_builder.get_variable(wire[i]); + if (i >= wire_poly.start_index() && i < wire_poly.end_index()) { + wire_poly.at(i) = circuit_builder.get_variable(wire[i]); + } else { + ASSERT(wire[i] == 0); + } } }); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/databus.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/databus.test.cpp index 57f0a88dee1..01fad4e3974 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/databus.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/databus.test.cpp @@ -4,7 +4,7 @@ #include "barretenberg/common/log.hpp" #include "barretenberg/goblin/mock_circuits.hpp" -#include "barretenberg/plonk_honk_shared/instance_inspector.hpp" +#include "barretenberg/plonk_honk_shared/proving_key_inspector.hpp" #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/instances.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_keys.hpp similarity index 97% rename from barretenberg/cpp/src/barretenberg/sumcheck/instance/instances.hpp rename to barretenberg/cpp/src/barretenberg/ultra_honk/decider_keys.hpp index ae07e38a471..882950d95db 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/instances.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_keys.hpp @@ -1,6 +1,6 @@ #pragma once -#include "barretenberg/sumcheck/instance/prover_instance.hpp" -#include "barretenberg/sumcheck/instance/verifier_instance.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" +#include "barretenberg/ultra_honk/decider_verification_key.hpp" namespace bb { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp index 0f19b78e6ce..5d8defd5036 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.cpp @@ -32,7 +32,10 @@ template void DeciderProver_::execute_relation_ch auto sumcheck = Sumcheck(polynomial_size, transcript); { ZoneScopedN("sumcheck.prove"); - sumcheck_output = sumcheck.prove(proving_key); + sumcheck_output = sumcheck.prove(proving_key->proving_key.polynomials, + proving_key->relation_parameters, + proving_key->alphas, + proving_key->gate_challenges); } } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp index a03519c2abc..c85a9520d47 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp @@ -4,9 +4,9 @@ #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" #include "barretenberg/sumcheck/sumcheck_output.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" namespace bb { diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.cpp similarity index 74% rename from barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp rename to barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.cpp index 555239874fd..1dcdaad737b 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.cpp @@ -1,4 +1,4 @@ -#include "prover_instance.hpp" +#include "decider_proving_key.hpp" #include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/plonk_honk_shared/composer/permutation_lib.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" @@ -57,25 +57,26 @@ void DeciderProvingKey_::construct_databus_polynomials(Circuit& circuit) // Note: We do not utilize a zero row for databus columns for (size_t idx = 0; idx < calldata.size(); ++idx) { - public_calldata[idx] = circuit.get_variable(calldata[idx]); // calldata values - calldata_read_counts[idx] = calldata.get_read_count(idx); // read counts - calldata_read_tags[idx] = calldata_read_counts[idx] > 0 ? 1 : 0; // has row been read or not + public_calldata.at(idx) = circuit.get_variable(calldata[idx]); // calldata values + calldata_read_counts.at(idx) = calldata.get_read_count(idx); // read counts + calldata_read_tags.at(idx) = calldata_read_counts[idx] > 0 ? 1 : 0; // has row been read or not } for (size_t idx = 0; idx < secondary_calldata.size(); ++idx) { - public_secondary_calldata[idx] = circuit.get_variable(secondary_calldata[idx]); // secondary_calldata values - secondary_calldata_read_counts[idx] = secondary_calldata.get_read_count(idx); // read counts - secondary_calldata_read_tags[idx] = secondary_calldata_read_counts[idx] > 0 ? 1 : 0; // has row been read or not + public_secondary_calldata.at(idx) = circuit.get_variable(secondary_calldata[idx]); // secondary_calldata values + secondary_calldata_read_counts.at(idx) = secondary_calldata.get_read_count(idx); // read counts + secondary_calldata_read_tags.at(idx) = + secondary_calldata_read_counts[idx] > 0 ? 1 : 0; // has row been read or not } for (size_t idx = 0; idx < return_data.size(); ++idx) { - public_return_data[idx] = circuit.get_variable(return_data[idx]); // return data values - return_data_read_counts[idx] = return_data.get_read_count(idx); // read counts - return_data_read_tags[idx] = return_data_read_counts[idx] > 0 ? 1 : 0; // has row been read or not + public_return_data.at(idx) = circuit.get_variable(return_data[idx]); // return data values + return_data_read_counts.at(idx) = return_data.get_read_count(idx); // read counts + return_data_read_tags.at(idx) = return_data_read_counts[idx] > 0 ? 1 : 0; // has row been read or not } auto& databus_id = proving_key.polynomials.databus_id; // Compute a simple identity polynomial for use in the databus lookup argument for (size_t i = 0; i < databus_id.size(); ++i) { - databus_id[i] = i; + databus_id.at(i) = i; } } diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp similarity index 93% rename from barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp rename to barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp index 7ef81472de5..46def876e81 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp @@ -8,7 +8,7 @@ #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_keccak.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_keccak_flavor.hpp" namespace bb { /** @@ -49,7 +49,6 @@ template class DeciderProvingKey_ { BB_OP_COUNT_TIME_NAME("DeciderProvingKey(Circuit&)"); circuit.add_gates_to_ensure_all_polys_are_non_zero(); circuit.finalize_circuit(); - info("finalized gate count: ", circuit.num_gates); // Set flag indicating whether the polynomials will be constructed with fixed block sizes for each gate type const bool is_structured = (trace_structure != TraceStructure::NONE); @@ -71,6 +70,7 @@ template class DeciderProvingKey_ { } { ZoneScopedN("constructing proving key"); + proving_key = ProvingKey(dyadic_circuit_size, circuit.public_inputs.size(), commitment_key); } @@ -84,8 +84,8 @@ template class DeciderProvingKey_ { } // First and last lagrange polynomials (in the full circuit size) - proving_key.polynomials.lagrange_first[0] = 1; - proving_key.polynomials.lagrange_last[dyadic_circuit_size - 1] = 1; + proving_key.polynomials.lagrange_first.at(0) = 1; + proving_key.polynomials.lagrange_last.at(dyadic_circuit_size - 1) = 1; construct_lookup_table_polynomials(proving_key.polynomials.get_tables(), circuit, dyadic_circuit_size); @@ -94,12 +94,10 @@ template class DeciderProvingKey_ { circuit, dyadic_circuit_size); - std::span public_wires_source = proving_key.polynomials.w_r; - // Construct the public inputs array for (size_t i = 0; i < proving_key.num_public_inputs; ++i) { size_t idx = i + proving_key.pub_inputs_offset; - proving_key.public_inputs.emplace_back(public_wires_source[idx]); + proving_key.public_inputs.emplace_back(proving_key.polynomials.w_r[idx]); } // Set the recursive proof indices diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/verifier_instance.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verification_key.hpp similarity index 100% rename from barretenberg/cpp/src/barretenberg/sumcheck/instance/verifier_instance.hpp rename to barretenberg/cpp/src/barretenberg/ultra_honk/decider_verification_key.hpp diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp index 19021e83e4c..8fb81f8749c 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp @@ -1,8 +1,8 @@ #include "decider_verifier.hpp" #include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" -#include "barretenberg/sumcheck/instance/verifier_instance.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/ultra_honk/decider_verification_key.hpp" namespace bb { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.hpp index af8615d4e6f..904b0a8b968 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.hpp @@ -3,8 +3,8 @@ #include "barretenberg/srs/global_crs.hpp" #include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/sumcheck/instance/verifier_instance.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" +#include "barretenberg/ultra_honk/decider_verification_key.hpp" namespace bb { template class DeciderVerifier_ { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_composer.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_composer.test.cpp index 741f6122b33..2bbac0e9a54 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_composer.test.cpp @@ -205,7 +205,7 @@ TEST_F(MegaHonkTests, MultipleCircuitsHonkAndMerge) auto commitment_key = std::make_shared(aggregate_op_queue_size); size_t idx = 0; for (const auto& result : op_queue->get_ultra_ops_commitments()) { - auto expected = commitment_key->commit(ultra_ops[idx++]); + auto expected = commitment_key->commit({ /* start index */ 0, ultra_ops[idx++] }); EXPECT_EQ(result, expected); } } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp index aac1f5fe906..94754892919 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp @@ -2,8 +2,8 @@ #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/polynomials/univariate.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" @@ -80,12 +80,15 @@ class MegaTranscriptTests : public ::testing::Test { manifest_expected.add_entry(round, "RETURN_DATA_INVERSES", frs_per_G); manifest_expected.add_entry(round, "Z_PERM", frs_per_G); + std::array alpha_labels; for (size_t i = 0; i < NUM_SUBRELATIONS - 1; i++) { std::string label = "alpha_" + std::to_string(i); - manifest_expected.add_challenge(round, label); - round++; + alpha_labels[i] = label; } + manifest_expected.add_challenge(round, alpha_labels); + round++; + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { std::string label = "Sumcheck:gate_challenge_" + std::to_string(i); manifest_expected.add_challenge(round, label); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index 4ff576e171a..283375f3340 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -49,7 +49,7 @@ template HonkProof MergeProver_::construct_proof() std::array t_shift; for (size_t i = 0; i < NUM_WIRES; ++i) { t_shift[i] = Polynomial(T_current[i]); - t_shift[i] -= T_prev[i]; + t_shift[i] -= { 0, T_prev[i] }; } // Compute/get commitments [t_i^{shift}], [T_{i-1}], and [T_i] and add to transcript @@ -112,7 +112,7 @@ template HonkProof MergeProver_::construct_proof() // Construct and commit to KZG quotient polynomial q = (f - v) / (X - kappa) auto quotient = batched_polynomial; - quotient[0] -= batched_eval; + quotient.at(0) -= batched_eval; quotient.factor_roots(kappa); auto quotient_commitment = pcs_commitment_key->commit(quotient); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp index 6fdbf6a3835..26e0f1cca5a 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp @@ -1,5 +1,6 @@ #include "barretenberg/ultra_honk/oink_prover.hpp" -#include "barretenberg/plonk_honk_shared/instance_inspector.hpp" +#include "barretenberg/common/op_count.hpp" +#include "barretenberg/plonk_honk_shared/proving_key_inspector.hpp" #include "barretenberg/relations/logderiv_lookup_relation.hpp" namespace bb { @@ -50,6 +51,7 @@ template void OinkProver::prove() */ template void OinkProver::execute_preamble_round() { + BB_OP_COUNT_TIME_NAME("OinkProver::execute_preamble_round"); const auto circuit_size = static_cast(proving_key->proving_key.circuit_size); const auto num_public_inputs = static_cast(proving_key->proving_key.num_public_inputs); transcript->send_to_verifier(domain_separator + "circuit_size", circuit_size); @@ -72,6 +74,7 @@ template void OinkProver::execute_preamble_round( */ template void OinkProver::execute_wire_commitments_round() { + BB_OP_COUNT_TIME_NAME("OinkProver::execute_wire_commitments_round"); // Commit to the first three wire polynomials // We only commit to the fourth wire polynomial after adding memory recordss { @@ -120,6 +123,7 @@ template void OinkProver::execute_wire_commitment */ template void OinkProver::execute_sorted_list_accumulator_round() { + BB_OP_COUNT_TIME_NAME("OinkProver::execute_sorted_list_accumulator_round"); // Get eta challenges auto [eta, eta_two, eta_three] = transcript->template get_challenges( domain_separator + "eta", domain_separator + "eta_two", domain_separator + "eta_three"); @@ -155,6 +159,7 @@ template void OinkProver::execute_sorted_list_acc */ template void OinkProver::execute_log_derivative_inverse_round() { + BB_OP_COUNT_TIME_NAME("OinkProver::execute_log_derivative_inverse_round"); auto [beta, gamma] = transcript->template get_challenges(domain_separator + "beta", domain_separator + "gamma"); proving_key->relation_parameters.beta = beta; proving_key->relation_parameters.gamma = gamma; @@ -191,6 +196,7 @@ template void OinkProver::execute_log_derivative_ */ template void OinkProver::execute_grand_product_computation_round() { + BB_OP_COUNT_TIME_NAME("OinkProver::execute_grand_product_computation_round"); proving_key->proving_key.compute_grand_product_polynomials(proving_key->relation_parameters); { @@ -202,10 +208,13 @@ template void OinkProver::execute_grand_product_c template typename Flavor::RelationSeparator OinkProver::generate_alphas_round() { + BB_OP_COUNT_TIME_NAME("OinkProver::generate_alphas_round"); RelationSeparator alphas; - for (size_t idx = 0; idx < alphas.size(); idx++) { - alphas[idx] = transcript->template get_challenge(domain_separator + "alpha_" + std::to_string(idx)); + std::array args; + for (size_t idx = 0; idx < alphas.size(); ++idx) { + args[idx] = domain_separator + "alpha_" + std::to_string(idx); } + alphas = transcript->template get_challenges(args); return alphas; } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.hpp index e056f671084..e252f7d904d 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.hpp @@ -21,9 +21,9 @@ #include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_keccak.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_keccak_flavor.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" namespace bb { /** diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp index b547a97b817..227fa145a44 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp @@ -148,10 +148,11 @@ template typename Flavor::RelationSeparator OinkVerifier< { // Get the relation separation challenges for sumcheck/combiner computation RelationSeparator alphas; - for (size_t idx = 0; idx < alphas.size(); idx++) { - alphas[idx] = transcript->template get_challenge(domain_separator + "alpha_" + std::to_string(idx)); + std::array args; + for (size_t idx = 0; idx < alphas.size(); ++idx) { + args[idx] = domain_separator + "alpha_" + std::to_string(idx); } - return alphas; + return transcript->template get_challenges(args); } template class OinkVerifier; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.hpp index 5920d7b0b40..fab7bcdff19 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.hpp @@ -5,8 +5,8 @@ #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_keccak.hpp" -#include "barretenberg/sumcheck/instance/verifier_instance.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_keccak_flavor.hpp" +#include "barretenberg/ultra_honk/decider_verification_key.hpp" namespace bb { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp index aa8805b5389..1958860a83a 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -11,7 +11,7 @@ #include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" #include using namespace bb; @@ -19,7 +19,7 @@ using namespace bb; void ensure_non_zero(auto& polynomial) { bool has_non_zero_coefficient = false; - for (auto& coeff : polynomial) { + for (auto& coeff : polynomial.coeffs()) { has_non_zero_coefficient |= !coeff.is_zero(); } ASSERT_TRUE(has_non_zero_coefficient); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp index d1c0e06573a..45f5a78c4d3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp @@ -179,7 +179,10 @@ TEST_F(SumcheckTestsRealCircuit, Ultra) prover_transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } decider_pk->gate_challenges = prover_gate_challenges; - auto prover_output = sumcheck_prover.prove(decider_pk); + auto prover_output = sumcheck_prover.prove(decider_pk->proving_key.polynomials, + decider_pk->relation_parameters, + decider_pk->alphas, + decider_pk->gate_challenges); auto verifier_transcript = Transcript::verifier_init_empty(prover_transcript); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp index be4d5979709..62dfe74c9c1 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp @@ -16,45 +16,40 @@ using namespace bb; -using DeciderProvingKey = DeciderProvingKey_; -using VerificationKey = UltraFlavor::VerificationKey; - -std::vector add_variables(auto& circuit_builder, std::vector variables) -{ - std::vector res; - for (size_t i = 0; i < variables.size(); i++) { - res.emplace_back(circuit_builder.add_variable(variables[i])); +template class UltraHonkTests : public ::testing::Test { + public: + using DeciderProvingKey = DeciderProvingKey_; + using VerificationKey = typename Flavor::VerificationKey; + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + + std::vector add_variables(auto& circuit_builder, std::vector variables) + { + std::vector res; + for (auto& variable : variables) { + res.emplace_back(circuit_builder.add_variable(variable)); + } + return res; } - return res; -} -void prove_and_verify(auto& circuit_builder, bool expected_result) -{ - auto proving_key = std::make_shared(circuit_builder); - UltraProver prover(proving_key); - auto verification_key = std::make_shared(proving_key->proving_key); - UltraVerifier verifier(verification_key); - auto proof = prover.construct_proof(); - bool verified = verifier.verify_proof(proof); - EXPECT_EQ(verified, expected_result); -}; - -void ensure_non_zero(auto& polynomial) -{ - bool has_non_zero_coefficient = false; - for (auto& coeff : polynomial) { - has_non_zero_coefficient |= !coeff.is_zero(); - } - ASSERT_TRUE(has_non_zero_coefficient); -} + void prove_and_verify(auto& circuit_builder, bool expected_result) + { + auto proving_key = std::make_shared(circuit_builder); + Prover prover(proving_key); + auto verification_key = std::make_shared(proving_key->proving_key); + Verifier verifier(verification_key); + auto proof = prover.construct_proof(); + bool verified = verifier.verify_proof(proof); + EXPECT_EQ(verified, expected_result); + }; -// TODO(https://github.com/AztecProtocol/barretenberg/issues/1075): Make the tests run on UltraKeccakFlavor as well so -// we have a means of checking issues without having to run the Solidity verifier contract. -class UltraHonkTests : public ::testing::Test { protected: static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } }; +using FlavorTypes = testing::Types; +TYPED_TEST_SUITE(UltraHonkTests, FlavorTypes); + /** * @brief A quick test to ensure that none of our polynomials are identically zero * @@ -62,15 +57,23 @@ class UltraHonkTests : public ::testing::Test { * to achieve non-zero polynomials * */ -TEST_F(UltraHonkTests, ANonZeroPolynomialIsAGoodPolynomial) +TYPED_TEST(UltraHonkTests, ANonZeroPolynomialIsAGoodPolynomial) { auto circuit_builder = UltraCircuitBuilder(); - auto proving_key = std::make_shared(circuit_builder); - UltraProver prover(proving_key); + auto proving_key = std::make_shared(circuit_builder); + typename TestFixture::Prover prover(proving_key); auto proof = prover.construct_proof(); auto& polynomials = proving_key->proving_key.polynomials; + auto ensure_non_zero = [](auto& polynomial) { + bool has_non_zero_coefficient = false; + for (auto& coeff : polynomial.coeffs()) { + has_non_zero_coefficient |= !coeff.is_zero(); + } + ASSERT_TRUE(has_non_zero_coefficient); + }; + for (auto& poly : polynomials.get_selectors()) { ensure_non_zero(poly); } @@ -88,7 +91,7 @@ TEST_F(UltraHonkTests, ANonZeroPolynomialIsAGoodPolynomial) * @brief Test proof construction/verification for a structured execution trace * */ -TEST_F(UltraHonkTests, StructuredTrace) +TYPED_TEST(UltraHonkTests, StructuredTrace) { auto builder = UltraCircuitBuilder(); size_t num_gates = 3; @@ -98,10 +101,10 @@ TEST_F(UltraHonkTests, StructuredTrace) // Construct an proving_key with a structured execution trace TraceStructure trace_structure = TraceStructure::SMALL_TEST; - auto proving_key = std::make_shared(builder, trace_structure); - UltraProver prover(proving_key); - auto verification_key = std::make_shared(proving_key->proving_key); - UltraVerifier verifier(verification_key); + auto proving_key = std::make_shared(builder, trace_structure); + typename TestFixture::Prover prover(proving_key); + auto verification_key = std::make_shared(proving_key->proving_key); + typename TestFixture::Verifier verifier(verification_key); auto proof = prover.construct_proof(); EXPECT_TRUE(verifier.verify_proof(proof)); } @@ -110,7 +113,7 @@ TEST_F(UltraHonkTests, StructuredTrace) * @brief Test simple circuit with public inputs * */ -TEST_F(UltraHonkTests, PublicInputs) +TYPED_TEST(UltraHonkTests, PublicInputs) { auto builder = UltraCircuitBuilder(); size_t num_gates = 10; @@ -118,10 +121,10 @@ TEST_F(UltraHonkTests, PublicInputs) // Add some arbitrary arithmetic gates that utilize public inputs MockCircuits::add_arithmetic_gates_with_public_inputs(builder, num_gates); - prove_and_verify(builder, /*expected_result=*/true); + TestFixture::prove_and_verify(builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, XorConstraint) +TYPED_TEST(UltraHonkTests, XorConstraint) { auto circuit_builder = UltraCircuitBuilder(); @@ -145,10 +148,10 @@ TEST_F(UltraHonkTests, XorConstraint) circuit_builder.create_gates_from_plookup_accumulators( plookup::MultiTableId::UINT32_XOR, lookup_accumulators, left_witness_index, right_witness_index); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, create_gates_from_plookup_accumulators) +TYPED_TEST(UltraHonkTests, create_gates_from_plookup_accumulators) { auto circuit_builder = UltraCircuitBuilder(); @@ -205,15 +208,17 @@ TEST_F(UltraHonkTests, create_gates_from_plookup_accumulators) } } - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } /** * @brief Test various failure modes for the lookup relation via bad input polynomials * */ -TEST_F(UltraHonkTests, LookupFailure) +TYPED_TEST(UltraHonkTests, LookupFailure) { + using DeciderProvingKey = typename TestFixture::DeciderProvingKey; + using VerificationKey = typename TestFixture::VerificationKey; // Construct a circuit with lookup and arithmetic gates auto construct_circuit_with_lookups = []() { UltraCircuitBuilder builder; @@ -225,9 +230,9 @@ TEST_F(UltraHonkTests, LookupFailure) }; auto prove_and_verify = [](auto& proving_key) { - UltraProver prover(proving_key); + typename TestFixture::Prover prover(proving_key); auto verification_key = std::make_shared(proving_key->proving_key); - UltraVerifier verifier(verification_key); + typename TestFixture::Verifier verifier(verification_key); auto proof = prover.construct_proof(); return verifier.verify_proof(proof); }; @@ -238,7 +243,7 @@ TEST_F(UltraHonkTests, LookupFailure) auto proving_key = std::make_shared(builder); - EXPECT_TRUE(prove_and_verify(proving_key)); + prove_and_verify(proving_key); } // Failure mode 1: bad read counts/tags @@ -250,11 +255,14 @@ TEST_F(UltraHonkTests, LookupFailure) // Erroneously update the read counts/tags at an arbitrary index // Note: updating only one or the other may not cause failure due to the design of the relation algebra. For - // example, the inverse is only computed if read tags is non-zero, otherwise the inverse at the row in question - // will be zero. So if read counts is incremented at some arbitrary index but read tags is not, the inverse will - // be 0 and the erroneous read_counts value will get multiplied by 0 in the relation. This is expected behavior. - polynomials.lookup_read_counts[25] = 1; - polynomials.lookup_read_tags[25] = 1; + // example, the inverse is only computed if read tags is non-zero, otherwise the inverse at the row in + // question will be zero. So if read counts is incremented at some arbitrary index but read tags is not, the + // inverse will be 0 and the erroneous read_counts value will get multiplied by 0 in the relation. This is + // expected behavior. + polynomials.lookup_read_counts = polynomials.lookup_read_counts.full(); + polynomials.lookup_read_counts.at(25) = 1; + polynomials.lookup_read_tags = polynomials.lookup_read_tags.full(); + polynomials.lookup_read_tags.at(25) = 1; EXPECT_FALSE(prove_and_verify(proving_key)); } @@ -266,14 +274,16 @@ TEST_F(UltraHonkTests, LookupFailure) auto proving_key = std::make_shared(builder); auto& polynomials = proving_key->proving_key.polynomials; + bool altered = false; // Find a lookup gate and alter one of the wire values - for (auto [q_lookup, wire_3] : zip_view(polynomials.q_lookup, polynomials.w_o)) { - if (!q_lookup.is_zero()) { - wire_3 += 1; + for (auto [i, q_lookup] : polynomials.q_lookup.indexed_values()) { + if (!q_lookup.is_zero() && polynomials.q_lookup.is_valid_set_index(i)) { + polynomials.w_o.at(i) += 1; + altered = true; break; } } - + EXPECT_TRUE(altered); EXPECT_FALSE(prove_and_verify(proving_key)); } @@ -285,14 +295,15 @@ TEST_F(UltraHonkTests, LookupFailure) auto& polynomials = proving_key->proving_key.polynomials; // Turn the lookup selector on for an arbitrary row where it is not already active + polynomials.q_lookup = polynomials.q_lookup.full(); EXPECT_TRUE(polynomials.q_lookup[25] != 1); - polynomials.q_lookup[25] = 1; + polynomials.q_lookup.at(25) = 1; EXPECT_FALSE(prove_and_verify(proving_key)); } } -TEST_F(UltraHonkTests, test_no_lookup_proof) +TYPED_TEST(UltraHonkTests, test_no_lookup_proof) { auto circuit_builder = UltraCircuitBuilder(); @@ -311,10 +322,10 @@ TEST_F(UltraHonkTests, test_no_lookup_proof) } } - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, test_elliptic_gate) +TYPED_TEST(UltraHonkTests, test_elliptic_gate) { typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; @@ -344,10 +355,10 @@ TEST_F(UltraHonkTests, test_elliptic_gate) y3 = circuit_builder.add_variable(p3.y); circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, -1 }); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, non_trivial_tag_permutation) +TYPED_TEST(UltraHonkTests, non_trivial_tag_permutation) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::random_element(); @@ -371,10 +382,10 @@ TEST_F(UltraHonkTests, non_trivial_tag_permutation) circuit_builder.assign_tag(c_idx, 2); circuit_builder.assign_tag(d_idx, 2); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, non_trivial_tag_permutation_and_cycles) +TYPED_TEST(UltraHonkTests, non_trivial_tag_permutation_and_cycles) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::random_element(); @@ -408,10 +419,10 @@ TEST_F(UltraHonkTests, non_trivial_tag_permutation_and_cycles) circuit_builder.create_add_gate( { e_idx, f_idx, circuit_builder.zero_idx, fr::one(), -fr::one(), fr::zero(), fr::zero() }); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, bad_tag_permutation) +TYPED_TEST(UltraHonkTests, bad_tag_permutation) { { auto circuit_builder = UltraCircuitBuilder(); @@ -434,7 +445,7 @@ TEST_F(UltraHonkTests, bad_tag_permutation) circuit_builder.assign_tag(c_idx, 2); circuit_builder.assign_tag(d_idx, 2); - prove_and_verify(circuit_builder, /*expected_result=*/false); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false); } // Same as above but without tag creation to check reason of failure is really tag mismatch { @@ -450,11 +461,11 @@ TEST_F(UltraHonkTests, bad_tag_permutation) circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx, 1, 1, 0, 0 }); circuit_builder.create_add_gate({ c_idx, d_idx, circuit_builder.zero_idx, 1, 1, 0, -1 }); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } } -TEST_F(UltraHonkTests, sort_widget) +TYPED_TEST(UltraHonkTests, sort_widget) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::one(); @@ -468,10 +479,10 @@ TEST_F(UltraHonkTests, sort_widget) auto d_idx = circuit_builder.add_variable(d); circuit_builder.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, sort_with_edges_gate) +TYPED_TEST(UltraHonkTests, sort_with_edges_gate) { fr a = fr::one(); fr b = fr(2); @@ -495,7 +506,7 @@ TEST_F(UltraHonkTests, sort_with_edges_gate) circuit_builder.create_sort_constraint_with_edges( { a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, a, h); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } { @@ -511,7 +522,7 @@ TEST_F(UltraHonkTests, sort_with_edges_gate) circuit_builder.create_sort_constraint_with_edges( { a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, a, g); - prove_and_verify(circuit_builder, /*expected_result=*/false); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false); } { auto circuit_builder = UltraCircuitBuilder(); @@ -526,7 +537,7 @@ TEST_F(UltraHonkTests, sort_with_edges_gate) circuit_builder.create_sort_constraint_with_edges( { a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, b, h); - prove_and_verify(circuit_builder, /*expected_result=*/false); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false); } { auto circuit_builder = UltraCircuitBuilder(); @@ -541,99 +552,101 @@ TEST_F(UltraHonkTests, sort_with_edges_gate) circuit_builder.create_sort_constraint_with_edges( { a_idx, b2_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, b, h); - prove_and_verify(circuit_builder, /*expected_result=*/false); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false); } { auto circuit_builder = UltraCircuitBuilder(); - auto idx = add_variables(circuit_builder, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25, - 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); + auto idx = + TestFixture::add_variables(circuit_builder, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25, + 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); circuit_builder.create_sort_constraint_with_edges(idx, 1, 45); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } { auto circuit_builder = UltraCircuitBuilder(); - auto idx = add_variables(circuit_builder, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25, - 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); + auto idx = + TestFixture::add_variables(circuit_builder, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25, + 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); circuit_builder.create_sort_constraint_with_edges(idx, 1, 29); - prove_and_verify(circuit_builder, /*expected_result=*/false); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false); } } -TEST_F(UltraHonkTests, range_constraint) +TYPED_TEST(UltraHonkTests, range_constraint) { { auto circuit_builder = UltraCircuitBuilder(); - auto indices = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); + auto indices = TestFixture::add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); for (size_t i = 0; i < indices.size(); i++) { circuit_builder.create_new_range_constraint(indices[i], 8); } // auto ind = {a_idx,b_idx,c_idx,d_idx,e_idx,f_idx,g_idx,h_idx}; circuit_builder.create_sort_constraint(indices); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } { auto circuit_builder = UltraCircuitBuilder(); - auto indices = add_variables(circuit_builder, { 3 }); + auto indices = TestFixture::add_variables(circuit_builder, { 3 }); for (size_t i = 0; i < indices.size(); i++) { circuit_builder.create_new_range_constraint(indices[i], 3); } // auto ind = {a_idx,b_idx,c_idx,d_idx,e_idx,f_idx,g_idx,h_idx}; circuit_builder.create_dummy_constraints(indices); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } { auto circuit_builder = UltraCircuitBuilder(); - auto indices = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 8, 25 }); + auto indices = TestFixture::add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 8, 25 }); for (size_t i = 0; i < indices.size(); i++) { circuit_builder.create_new_range_constraint(indices[i], 8); } circuit_builder.create_sort_constraint(indices); - prove_and_verify(circuit_builder, /*expected_result=*/false); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false); } { auto circuit_builder = UltraCircuitBuilder(); - auto indices = - add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 10, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 19, 51 }); + auto indices = TestFixture::add_variables( + circuit_builder, { 1, 2, 3, 4, 5, 6, 10, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 19, 51 }); for (size_t i = 0; i < indices.size(); i++) { circuit_builder.create_new_range_constraint(indices[i], 128); } circuit_builder.create_dummy_constraints(indices); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } { auto circuit_builder = UltraCircuitBuilder(); - auto indices = - add_variables(circuit_builder, { 1, 2, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 }); + auto indices = TestFixture::add_variables( + circuit_builder, { 1, 2, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 }); for (size_t i = 0; i < indices.size(); i++) { circuit_builder.create_new_range_constraint(indices[i], 79); } circuit_builder.create_dummy_constraints(indices); - prove_and_verify(circuit_builder, /*expected_result=*/false); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false); } { auto circuit_builder = UltraCircuitBuilder(); - auto indices = - add_variables(circuit_builder, { 1, 0, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 }); + auto indices = TestFixture::add_variables( + circuit_builder, { 1, 0, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 }); for (size_t i = 0; i < indices.size(); i++) { circuit_builder.create_new_range_constraint(indices[i], 79); } circuit_builder.create_dummy_constraints(indices); - prove_and_verify(circuit_builder, /*expected_result=*/false); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false); } } -TEST_F(UltraHonkTests, range_with_gates) +TYPED_TEST(UltraHonkTests, range_with_gates) { auto circuit_builder = UltraCircuitBuilder(); - auto idx = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); + auto idx = TestFixture::add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); for (size_t i = 0; i < idx.size(); i++) { circuit_builder.create_new_range_constraint(idx[i], 8); } @@ -645,13 +658,13 @@ TEST_F(UltraHonkTests, range_with_gates) circuit_builder.create_add_gate( { idx[6], idx[7], circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), -15 }); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, range_with_gates_where_range_is_not_a_power_of_two) +TYPED_TEST(UltraHonkTests, range_with_gates_where_range_is_not_a_power_of_two) { auto circuit_builder = UltraCircuitBuilder(); - auto idx = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); + auto idx = TestFixture::add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); for (size_t i = 0; i < idx.size(); i++) { circuit_builder.create_new_range_constraint(idx[i], 12); } @@ -663,10 +676,10 @@ TEST_F(UltraHonkTests, range_with_gates_where_range_is_not_a_power_of_two) circuit_builder.create_add_gate( { idx[6], idx[7], circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), -15 }); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, sort_widget_complex) +TYPED_TEST(UltraHonkTests, sort_widget_complex) { { @@ -677,7 +690,7 @@ TEST_F(UltraHonkTests, sort_widget_complex) ind.emplace_back(circuit_builder.add_variable(a[i])); circuit_builder.create_sort_constraint(ind); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } { @@ -688,11 +701,11 @@ TEST_F(UltraHonkTests, sort_widget_complex) ind.emplace_back(circuit_builder.add_variable(a[i])); circuit_builder.create_sort_constraint(ind); - prove_and_verify(circuit_builder, /*expected_result=*/false); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false); } } -TEST_F(UltraHonkTests, sort_widget_neg) +TYPED_TEST(UltraHonkTests, sort_widget_neg) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::one(); @@ -706,10 +719,10 @@ TEST_F(UltraHonkTests, sort_widget_neg) auto d_idx = circuit_builder.add_variable(d); circuit_builder.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); - prove_and_verify(circuit_builder, /*expected_result=*/false); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/false); } -TEST_F(UltraHonkTests, composed_range_constraint) +TYPED_TEST(UltraHonkTests, composed_range_constraint) { auto circuit_builder = UltraCircuitBuilder(); auto c = fr::random_element(); @@ -719,10 +732,10 @@ TEST_F(UltraHonkTests, composed_range_constraint) circuit_builder.create_add_gate({ a_idx, circuit_builder.zero_idx, circuit_builder.zero_idx, 1, 0, 0, -fr(e) }); circuit_builder.decompose_into_default_range(a_idx, 134); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, non_native_field_multiplication) +TYPED_TEST(UltraHonkTests, non_native_field_multiplication) { using fq = fq; auto circuit_builder = UltraCircuitBuilder(); @@ -775,10 +788,10 @@ TEST_F(UltraHonkTests, non_native_field_multiplication) const auto [lo_1_idx, hi_1_idx] = circuit_builder.evaluate_non_native_field_multiplication(inputs); circuit_builder.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, rom) +TYPED_TEST(UltraHonkTests, rom) { auto circuit_builder = UltraCircuitBuilder(); @@ -816,10 +829,10 @@ TEST_F(UltraHonkTests, rom) 0, }); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, ram) +TYPED_TEST(UltraHonkTests, ram) { auto circuit_builder = UltraCircuitBuilder(); @@ -879,10 +892,10 @@ TEST_F(UltraHonkTests, ram) }, false); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkTests, range_checks_on_duplicates) +TYPED_TEST(UltraHonkTests, range_checks_on_duplicates) { auto circuit_builder = UltraCircuitBuilder(); @@ -914,14 +927,14 @@ TEST_F(UltraHonkTests, range_checks_on_duplicates) }, false); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } // Ensure copy constraints added on variables smaller than 2^14, which have been previously // range constrained, do not break the set equivalence checks because of indices mismatch. // 2^14 is DEFAULT_PLOOKUP_RANGE_BITNUM i.e. the maximum size before a variable gets sliced // before range constraints are applied to it. -TEST_F(UltraHonkTests, range_constraint_small_variable) +TYPED_TEST(UltraHonkTests, range_constraint_small_variable) { auto circuit_builder = UltraCircuitBuilder(); @@ -937,5 +950,5 @@ TEST_F(UltraHonkTests, range_constraint_small_variable) circuit_builder.create_range_constraint(c_idx, 8, "bad range"); circuit_builder.assert_equal(a_idx, c_idx); - prove_and_verify(circuit_builder, /*expected_result=*/true); + TestFixture::prove_and_verify(circuit_builder, /*expected_result=*/true); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp index 61837b11a76..6ab19509eb6 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp @@ -4,9 +4,9 @@ #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" #include "barretenberg/sumcheck/sumcheck_output.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" namespace bb { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp index c1cd6ff054a..29b4c87172e 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp @@ -3,8 +3,8 @@ #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" @@ -65,12 +65,15 @@ class UltraTranscriptTests : public ::testing::Test { manifest_expected.add_entry(round, "LOOKUP_INVERSES", frs_per_G); manifest_expected.add_entry(round, "Z_PERM", frs_per_G); + std::array alpha_labels; for (size_t i = 0; i < NUM_SUBRELATIONS - 1; i++) { std::string label = "alpha_" + std::to_string(i); - manifest_expected.add_challenge(round, label); - round++; + alpha_labels[i] = label; } + manifest_expected.add_challenge(round, alpha_labels); + round++; + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { std::string label = "Sumcheck:gate_challenge_" + std::to_string(i); manifest_expected.add_challenge(round, label); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp index 2aeb11326a3..71bebc42cf4 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp @@ -3,8 +3,8 @@ #include "barretenberg/srs/global_crs.hpp" #include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/sumcheck/instance//verifier_instance.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" +#include "barretenberg/ultra_honk/decider_verification_key.hpp" #include "barretenberg/ultra_honk/decider_verifier.hpp" namespace bb { diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/circuit_builder.cpp index 72e8e628942..8343c01fc5f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/circuit_builder.cpp @@ -19,656 +19,668 @@ AvmCircuitBuilder::ProverPolynomials AvmCircuitBuilder::compute_polynomials() co ProverPolynomials polys; // Allocate mem for each column - for (auto& poly : polys.get_all()) { - poly = Polynomial(num_rows); + + for (auto& poly : polys.get_to_be_shifted()) { + poly = Polynomial{ /*memory size*/ num_rows - 1, + /*largest possible index*/ num_rows, + /*make shiftable with offset*/ 1 }; + } + // catch-all with fully formed polynomials + for (auto& poly : polys.get_unshifted()) { + if (poly.is_empty()) { + // Not set above + poly = Polynomial{ /*memory size*/ num_rows, /*largest possible index*/ num_rows }; + } } for (size_t i = 0; i < rows.size(); i++) { - polys.byte_lookup_sel_bin[i] = rows[i].byte_lookup_sel_bin; - polys.byte_lookup_table_byte_lengths[i] = rows[i].byte_lookup_table_byte_lengths; - polys.byte_lookup_table_in_tags[i] = rows[i].byte_lookup_table_in_tags; - polys.byte_lookup_table_input_a[i] = rows[i].byte_lookup_table_input_a; - polys.byte_lookup_table_input_b[i] = rows[i].byte_lookup_table_input_b; - polys.byte_lookup_table_op_id[i] = rows[i].byte_lookup_table_op_id; - polys.byte_lookup_table_output[i] = rows[i].byte_lookup_table_output; - polys.gas_base_da_gas_fixed_table[i] = rows[i].gas_base_da_gas_fixed_table; - polys.gas_base_l2_gas_fixed_table[i] = rows[i].gas_base_l2_gas_fixed_table; - polys.gas_dyn_da_gas_fixed_table[i] = rows[i].gas_dyn_da_gas_fixed_table; - polys.gas_dyn_l2_gas_fixed_table[i] = rows[i].gas_dyn_l2_gas_fixed_table; - polys.gas_sel_gas_cost[i] = rows[i].gas_sel_gas_cost; - polys.main_clk[i] = rows[i].main_clk; - polys.main_sel_first[i] = rows[i].main_sel_first; - polys.main_zeroes[i] = rows[i].main_zeroes; - polys.powers_power_of_2[i] = rows[i].powers_power_of_2; - polys.main_kernel_inputs[i] = rows[i].main_kernel_inputs; - polys.main_kernel_value_out[i] = rows[i].main_kernel_value_out; - polys.main_kernel_side_effect_out[i] = rows[i].main_kernel_side_effect_out; - polys.main_kernel_metadata_out[i] = rows[i].main_kernel_metadata_out; - polys.main_calldata[i] = rows[i].main_calldata; - polys.main_returndata[i] = rows[i].main_returndata; - polys.alu_a_hi[i] = rows[i].alu_a_hi; - polys.alu_a_lo[i] = rows[i].alu_a_lo; - polys.alu_b_hi[i] = rows[i].alu_b_hi; - polys.alu_b_lo[i] = rows[i].alu_b_lo; - polys.alu_b_pow[i] = rows[i].alu_b_pow; - polys.alu_c_hi[i] = rows[i].alu_c_hi; - polys.alu_c_lo[i] = rows[i].alu_c_lo; - polys.alu_cf[i] = rows[i].alu_cf; - polys.alu_clk[i] = rows[i].alu_clk; - polys.alu_cmp_gadget_gt[i] = rows[i].alu_cmp_gadget_gt; - polys.alu_cmp_gadget_input_a[i] = rows[i].alu_cmp_gadget_input_a; - polys.alu_cmp_gadget_input_b[i] = rows[i].alu_cmp_gadget_input_b; - polys.alu_cmp_gadget_result[i] = rows[i].alu_cmp_gadget_result; - polys.alu_cmp_gadget_sel[i] = rows[i].alu_cmp_gadget_sel; - polys.alu_ff_tag[i] = rows[i].alu_ff_tag; - polys.alu_ia[i] = rows[i].alu_ia; - polys.alu_ib[i] = rows[i].alu_ib; - polys.alu_ic[i] = rows[i].alu_ic; - polys.alu_in_tag[i] = rows[i].alu_in_tag; - polys.alu_max_bits_sub_b_bits[i] = rows[i].alu_max_bits_sub_b_bits; - polys.alu_max_bits_sub_b_pow[i] = rows[i].alu_max_bits_sub_b_pow; - polys.alu_op_add[i] = rows[i].alu_op_add; - polys.alu_op_cast[i] = rows[i].alu_op_cast; - polys.alu_op_div[i] = rows[i].alu_op_div; - polys.alu_op_eq[i] = rows[i].alu_op_eq; - polys.alu_op_lt[i] = rows[i].alu_op_lt; - polys.alu_op_lte[i] = rows[i].alu_op_lte; - polys.alu_op_mul[i] = rows[i].alu_op_mul; - polys.alu_op_not[i] = rows[i].alu_op_not; - polys.alu_op_shl[i] = rows[i].alu_op_shl; - polys.alu_op_shr[i] = rows[i].alu_op_shr; - polys.alu_op_sub[i] = rows[i].alu_op_sub; - polys.alu_partial_prod_hi[i] = rows[i].alu_partial_prod_hi; - polys.alu_partial_prod_lo[i] = rows[i].alu_partial_prod_lo; - polys.alu_range_check_input_value[i] = rows[i].alu_range_check_input_value; - polys.alu_range_check_num_bits[i] = rows[i].alu_range_check_num_bits; - polys.alu_range_check_sel[i] = rows[i].alu_range_check_sel; - polys.alu_remainder[i] = rows[i].alu_remainder; - polys.alu_sel_alu[i] = rows[i].alu_sel_alu; - polys.alu_sel_cmp[i] = rows[i].alu_sel_cmp; - polys.alu_sel_shift_which[i] = rows[i].alu_sel_shift_which; - polys.alu_u128_tag[i] = rows[i].alu_u128_tag; - polys.alu_u16_tag[i] = rows[i].alu_u16_tag; - polys.alu_u32_tag[i] = rows[i].alu_u32_tag; - polys.alu_u64_tag[i] = rows[i].alu_u64_tag; - polys.alu_u8_tag[i] = rows[i].alu_u8_tag; - polys.alu_zero_shift[i] = rows[i].alu_zero_shift; - polys.binary_acc_ia[i] = rows[i].binary_acc_ia; - polys.binary_acc_ib[i] = rows[i].binary_acc_ib; - polys.binary_acc_ic[i] = rows[i].binary_acc_ic; - polys.binary_clk[i] = rows[i].binary_clk; - polys.binary_ia_bytes[i] = rows[i].binary_ia_bytes; - polys.binary_ib_bytes[i] = rows[i].binary_ib_bytes; - polys.binary_ic_bytes[i] = rows[i].binary_ic_bytes; - polys.binary_in_tag[i] = rows[i].binary_in_tag; - polys.binary_mem_tag_ctr[i] = rows[i].binary_mem_tag_ctr; - polys.binary_mem_tag_ctr_inv[i] = rows[i].binary_mem_tag_ctr_inv; - polys.binary_op_id[i] = rows[i].binary_op_id; - polys.binary_sel_bin[i] = rows[i].binary_sel_bin; - polys.binary_start[i] = rows[i].binary_start; - polys.cmp_a_hi[i] = rows[i].cmp_a_hi; - polys.cmp_a_lo[i] = rows[i].cmp_a_lo; - polys.cmp_b_hi[i] = rows[i].cmp_b_hi; - polys.cmp_b_lo[i] = rows[i].cmp_b_lo; - polys.cmp_borrow[i] = rows[i].cmp_borrow; - polys.cmp_clk[i] = rows[i].cmp_clk; - polys.cmp_cmp_rng_ctr[i] = rows[i].cmp_cmp_rng_ctr; - polys.cmp_input_a[i] = rows[i].cmp_input_a; - polys.cmp_input_b[i] = rows[i].cmp_input_b; - polys.cmp_op_eq[i] = rows[i].cmp_op_eq; - polys.cmp_op_eq_diff_inv[i] = rows[i].cmp_op_eq_diff_inv; - polys.cmp_op_gt[i] = rows[i].cmp_op_gt; - polys.cmp_p_a_borrow[i] = rows[i].cmp_p_a_borrow; - polys.cmp_p_b_borrow[i] = rows[i].cmp_p_b_borrow; - polys.cmp_p_sub_a_hi[i] = rows[i].cmp_p_sub_a_hi; - polys.cmp_p_sub_a_lo[i] = rows[i].cmp_p_sub_a_lo; - polys.cmp_p_sub_b_hi[i] = rows[i].cmp_p_sub_b_hi; - polys.cmp_p_sub_b_lo[i] = rows[i].cmp_p_sub_b_lo; - polys.cmp_range_chk_clk[i] = rows[i].cmp_range_chk_clk; - polys.cmp_res_hi[i] = rows[i].cmp_res_hi; - polys.cmp_res_lo[i] = rows[i].cmp_res_lo; - polys.cmp_result[i] = rows[i].cmp_result; - polys.cmp_sel_cmp[i] = rows[i].cmp_sel_cmp; - polys.cmp_sel_rng_chk[i] = rows[i].cmp_sel_rng_chk; - polys.cmp_shift_sel[i] = rows[i].cmp_shift_sel; - polys.conversion_clk[i] = rows[i].conversion_clk; - polys.conversion_input[i] = rows[i].conversion_input; - polys.conversion_num_limbs[i] = rows[i].conversion_num_limbs; - polys.conversion_radix[i] = rows[i].conversion_radix; - polys.conversion_sel_to_radix_le[i] = rows[i].conversion_sel_to_radix_le; - polys.keccakf1600_clk[i] = rows[i].keccakf1600_clk; - polys.keccakf1600_input[i] = rows[i].keccakf1600_input; - polys.keccakf1600_output[i] = rows[i].keccakf1600_output; - polys.keccakf1600_sel_keccakf1600[i] = rows[i].keccakf1600_sel_keccakf1600; - polys.main_abs_da_rem_gas[i] = rows[i].main_abs_da_rem_gas; - polys.main_abs_l2_rem_gas[i] = rows[i].main_abs_l2_rem_gas; - polys.main_alu_in_tag[i] = rows[i].main_alu_in_tag; - polys.main_base_da_gas_op_cost[i] = rows[i].main_base_da_gas_op_cost; - polys.main_base_l2_gas_op_cost[i] = rows[i].main_base_l2_gas_op_cost; - polys.main_bin_op_id[i] = rows[i].main_bin_op_id; - polys.main_call_ptr[i] = rows[i].main_call_ptr; - polys.main_da_gas_remaining[i] = rows[i].main_da_gas_remaining; - polys.main_da_out_of_gas[i] = rows[i].main_da_out_of_gas; - polys.main_dyn_da_gas_op_cost[i] = rows[i].main_dyn_da_gas_op_cost; - polys.main_dyn_gas_multiplier[i] = rows[i].main_dyn_gas_multiplier; - polys.main_dyn_l2_gas_op_cost[i] = rows[i].main_dyn_l2_gas_op_cost; - polys.main_emit_l2_to_l1_msg_write_offset[i] = rows[i].main_emit_l2_to_l1_msg_write_offset; - polys.main_emit_note_hash_write_offset[i] = rows[i].main_emit_note_hash_write_offset; - polys.main_emit_nullifier_write_offset[i] = rows[i].main_emit_nullifier_write_offset; - polys.main_emit_unencrypted_log_write_offset[i] = rows[i].main_emit_unencrypted_log_write_offset; - polys.main_ia[i] = rows[i].main_ia; - polys.main_ib[i] = rows[i].main_ib; - polys.main_ic[i] = rows[i].main_ic; - polys.main_id[i] = rows[i].main_id; - polys.main_id_zero[i] = rows[i].main_id_zero; - polys.main_ind_addr_a[i] = rows[i].main_ind_addr_a; - polys.main_ind_addr_b[i] = rows[i].main_ind_addr_b; - polys.main_ind_addr_c[i] = rows[i].main_ind_addr_c; - polys.main_ind_addr_d[i] = rows[i].main_ind_addr_d; - polys.main_internal_return_ptr[i] = rows[i].main_internal_return_ptr; - polys.main_inv[i] = rows[i].main_inv; - polys.main_kernel_in_offset[i] = rows[i].main_kernel_in_offset; - polys.main_kernel_out_offset[i] = rows[i].main_kernel_out_offset; - polys.main_l1_to_l2_msg_exists_write_offset[i] = rows[i].main_l1_to_l2_msg_exists_write_offset; - polys.main_l2_gas_remaining[i] = rows[i].main_l2_gas_remaining; - polys.main_l2_out_of_gas[i] = rows[i].main_l2_out_of_gas; - polys.main_mem_addr_a[i] = rows[i].main_mem_addr_a; - polys.main_mem_addr_b[i] = rows[i].main_mem_addr_b; - polys.main_mem_addr_c[i] = rows[i].main_mem_addr_c; - polys.main_mem_addr_d[i] = rows[i].main_mem_addr_d; - polys.main_note_hash_exist_write_offset[i] = rows[i].main_note_hash_exist_write_offset; - polys.main_nullifier_exists_write_offset[i] = rows[i].main_nullifier_exists_write_offset; - polys.main_nullifier_non_exists_write_offset[i] = rows[i].main_nullifier_non_exists_write_offset; - polys.main_op_err[i] = rows[i].main_op_err; - polys.main_opcode_val[i] = rows[i].main_opcode_val; - polys.main_pc[i] = rows[i].main_pc; - polys.main_r_in_tag[i] = rows[i].main_r_in_tag; - polys.main_rwa[i] = rows[i].main_rwa; - polys.main_rwb[i] = rows[i].main_rwb; - polys.main_rwc[i] = rows[i].main_rwc; - polys.main_rwd[i] = rows[i].main_rwd; - polys.main_sel_alu[i] = rows[i].main_sel_alu; - polys.main_sel_bin[i] = rows[i].main_sel_bin; - polys.main_sel_calldata[i] = rows[i].main_sel_calldata; - polys.main_sel_execution_row[i] = rows[i].main_sel_execution_row; - polys.main_sel_kernel_inputs[i] = rows[i].main_sel_kernel_inputs; - polys.main_sel_kernel_out[i] = rows[i].main_sel_kernel_out; - polys.main_sel_last[i] = rows[i].main_sel_last; - polys.main_sel_mem_op_a[i] = rows[i].main_sel_mem_op_a; - polys.main_sel_mem_op_b[i] = rows[i].main_sel_mem_op_b; - polys.main_sel_mem_op_c[i] = rows[i].main_sel_mem_op_c; - polys.main_sel_mem_op_d[i] = rows[i].main_sel_mem_op_d; - polys.main_sel_mov_ia_to_ic[i] = rows[i].main_sel_mov_ia_to_ic; - polys.main_sel_mov_ib_to_ic[i] = rows[i].main_sel_mov_ib_to_ic; - polys.main_sel_op_add[i] = rows[i].main_sel_op_add; - polys.main_sel_op_address[i] = rows[i].main_sel_op_address; - polys.main_sel_op_and[i] = rows[i].main_sel_op_and; - polys.main_sel_op_block_number[i] = rows[i].main_sel_op_block_number; - polys.main_sel_op_calldata_copy[i] = rows[i].main_sel_op_calldata_copy; - polys.main_sel_op_cast[i] = rows[i].main_sel_op_cast; - polys.main_sel_op_chain_id[i] = rows[i].main_sel_op_chain_id; - polys.main_sel_op_cmov[i] = rows[i].main_sel_op_cmov; - polys.main_sel_op_coinbase[i] = rows[i].main_sel_op_coinbase; - polys.main_sel_op_dagasleft[i] = rows[i].main_sel_op_dagasleft; - polys.main_sel_op_div[i] = rows[i].main_sel_op_div; - polys.main_sel_op_ecadd[i] = rows[i].main_sel_op_ecadd; - polys.main_sel_op_emit_l2_to_l1_msg[i] = rows[i].main_sel_op_emit_l2_to_l1_msg; - polys.main_sel_op_emit_note_hash[i] = rows[i].main_sel_op_emit_note_hash; - polys.main_sel_op_emit_nullifier[i] = rows[i].main_sel_op_emit_nullifier; - polys.main_sel_op_emit_unencrypted_log[i] = rows[i].main_sel_op_emit_unencrypted_log; - polys.main_sel_op_eq[i] = rows[i].main_sel_op_eq; - polys.main_sel_op_external_call[i] = rows[i].main_sel_op_external_call; - polys.main_sel_op_external_return[i] = rows[i].main_sel_op_external_return; - polys.main_sel_op_external_revert[i] = rows[i].main_sel_op_external_revert; - polys.main_sel_op_fdiv[i] = rows[i].main_sel_op_fdiv; - polys.main_sel_op_fee_per_da_gas[i] = rows[i].main_sel_op_fee_per_da_gas; - polys.main_sel_op_fee_per_l2_gas[i] = rows[i].main_sel_op_fee_per_l2_gas; - polys.main_sel_op_function_selector[i] = rows[i].main_sel_op_function_selector; - polys.main_sel_op_get_contract_instance[i] = rows[i].main_sel_op_get_contract_instance; - polys.main_sel_op_internal_call[i] = rows[i].main_sel_op_internal_call; - polys.main_sel_op_internal_return[i] = rows[i].main_sel_op_internal_return; - polys.main_sel_op_jump[i] = rows[i].main_sel_op_jump; - polys.main_sel_op_jumpi[i] = rows[i].main_sel_op_jumpi; - polys.main_sel_op_keccak[i] = rows[i].main_sel_op_keccak; - polys.main_sel_op_l1_to_l2_msg_exists[i] = rows[i].main_sel_op_l1_to_l2_msg_exists; - polys.main_sel_op_l2gasleft[i] = rows[i].main_sel_op_l2gasleft; - polys.main_sel_op_lt[i] = rows[i].main_sel_op_lt; - polys.main_sel_op_lte[i] = rows[i].main_sel_op_lte; - polys.main_sel_op_mov[i] = rows[i].main_sel_op_mov; - polys.main_sel_op_msm[i] = rows[i].main_sel_op_msm; - polys.main_sel_op_mul[i] = rows[i].main_sel_op_mul; - polys.main_sel_op_not[i] = rows[i].main_sel_op_not; - polys.main_sel_op_note_hash_exists[i] = rows[i].main_sel_op_note_hash_exists; - polys.main_sel_op_nullifier_exists[i] = rows[i].main_sel_op_nullifier_exists; - polys.main_sel_op_or[i] = rows[i].main_sel_op_or; - polys.main_sel_op_pedersen[i] = rows[i].main_sel_op_pedersen; - polys.main_sel_op_pedersen_commit[i] = rows[i].main_sel_op_pedersen_commit; - polys.main_sel_op_poseidon2[i] = rows[i].main_sel_op_poseidon2; - polys.main_sel_op_radix_le[i] = rows[i].main_sel_op_radix_le; - polys.main_sel_op_sender[i] = rows[i].main_sel_op_sender; - polys.main_sel_op_set[i] = rows[i].main_sel_op_set; - polys.main_sel_op_sha256[i] = rows[i].main_sel_op_sha256; - polys.main_sel_op_shl[i] = rows[i].main_sel_op_shl; - polys.main_sel_op_shr[i] = rows[i].main_sel_op_shr; - polys.main_sel_op_sload[i] = rows[i].main_sel_op_sload; - polys.main_sel_op_sstore[i] = rows[i].main_sel_op_sstore; - polys.main_sel_op_storage_address[i] = rows[i].main_sel_op_storage_address; - polys.main_sel_op_sub[i] = rows[i].main_sel_op_sub; - polys.main_sel_op_timestamp[i] = rows[i].main_sel_op_timestamp; - polys.main_sel_op_transaction_fee[i] = rows[i].main_sel_op_transaction_fee; - polys.main_sel_op_version[i] = rows[i].main_sel_op_version; - polys.main_sel_op_xor[i] = rows[i].main_sel_op_xor; - polys.main_sel_q_kernel_lookup[i] = rows[i].main_sel_q_kernel_lookup; - polys.main_sel_q_kernel_output_lookup[i] = rows[i].main_sel_q_kernel_output_lookup; - polys.main_sel_resolve_ind_addr_a[i] = rows[i].main_sel_resolve_ind_addr_a; - polys.main_sel_resolve_ind_addr_b[i] = rows[i].main_sel_resolve_ind_addr_b; - polys.main_sel_resolve_ind_addr_c[i] = rows[i].main_sel_resolve_ind_addr_c; - polys.main_sel_resolve_ind_addr_d[i] = rows[i].main_sel_resolve_ind_addr_d; - polys.main_sel_returndata[i] = rows[i].main_sel_returndata; - polys.main_sel_rng_16[i] = rows[i].main_sel_rng_16; - polys.main_sel_rng_8[i] = rows[i].main_sel_rng_8; - polys.main_sel_slice_gadget[i] = rows[i].main_sel_slice_gadget; - polys.main_side_effect_counter[i] = rows[i].main_side_effect_counter; - polys.main_sload_write_offset[i] = rows[i].main_sload_write_offset; - polys.main_space_id[i] = rows[i].main_space_id; - polys.main_sstore_write_offset[i] = rows[i].main_sstore_write_offset; - polys.main_tag_err[i] = rows[i].main_tag_err; - polys.main_w_in_tag[i] = rows[i].main_w_in_tag; - polys.mem_addr[i] = rows[i].mem_addr; - polys.mem_clk[i] = rows[i].mem_clk; - polys.mem_diff[i] = rows[i].mem_diff; - polys.mem_glob_addr[i] = rows[i].mem_glob_addr; - polys.mem_last[i] = rows[i].mem_last; - polys.mem_lastAccess[i] = rows[i].mem_lastAccess; - polys.mem_one_min_inv[i] = rows[i].mem_one_min_inv; - polys.mem_r_in_tag[i] = rows[i].mem_r_in_tag; - polys.mem_rw[i] = rows[i].mem_rw; - polys.mem_sel_mem[i] = rows[i].mem_sel_mem; - polys.mem_sel_mov_ia_to_ic[i] = rows[i].mem_sel_mov_ia_to_ic; - polys.mem_sel_mov_ib_to_ic[i] = rows[i].mem_sel_mov_ib_to_ic; - polys.mem_sel_op_a[i] = rows[i].mem_sel_op_a; - polys.mem_sel_op_b[i] = rows[i].mem_sel_op_b; - polys.mem_sel_op_c[i] = rows[i].mem_sel_op_c; - polys.mem_sel_op_cmov[i] = rows[i].mem_sel_op_cmov; - polys.mem_sel_op_d[i] = rows[i].mem_sel_op_d; - polys.mem_sel_op_poseidon_read_a[i] = rows[i].mem_sel_op_poseidon_read_a; - polys.mem_sel_op_poseidon_read_b[i] = rows[i].mem_sel_op_poseidon_read_b; - polys.mem_sel_op_poseidon_read_c[i] = rows[i].mem_sel_op_poseidon_read_c; - polys.mem_sel_op_poseidon_read_d[i] = rows[i].mem_sel_op_poseidon_read_d; - polys.mem_sel_op_poseidon_write_a[i] = rows[i].mem_sel_op_poseidon_write_a; - polys.mem_sel_op_poseidon_write_b[i] = rows[i].mem_sel_op_poseidon_write_b; - polys.mem_sel_op_poseidon_write_c[i] = rows[i].mem_sel_op_poseidon_write_c; - polys.mem_sel_op_poseidon_write_d[i] = rows[i].mem_sel_op_poseidon_write_d; - polys.mem_sel_op_slice[i] = rows[i].mem_sel_op_slice; - polys.mem_sel_resolve_ind_addr_a[i] = rows[i].mem_sel_resolve_ind_addr_a; - polys.mem_sel_resolve_ind_addr_b[i] = rows[i].mem_sel_resolve_ind_addr_b; - polys.mem_sel_resolve_ind_addr_c[i] = rows[i].mem_sel_resolve_ind_addr_c; - polys.mem_sel_resolve_ind_addr_d[i] = rows[i].mem_sel_resolve_ind_addr_d; - polys.mem_sel_rng_chk[i] = rows[i].mem_sel_rng_chk; - polys.mem_skip_check_tag[i] = rows[i].mem_skip_check_tag; - polys.mem_space_id[i] = rows[i].mem_space_id; - polys.mem_tag[i] = rows[i].mem_tag; - polys.mem_tag_err[i] = rows[i].mem_tag_err; - polys.mem_tsp[i] = rows[i].mem_tsp; - polys.mem_val[i] = rows[i].mem_val; - polys.mem_w_in_tag[i] = rows[i].mem_w_in_tag; - polys.pedersen_clk[i] = rows[i].pedersen_clk; - polys.pedersen_input[i] = rows[i].pedersen_input; - polys.pedersen_output[i] = rows[i].pedersen_output; - polys.pedersen_sel_pedersen[i] = rows[i].pedersen_sel_pedersen; - polys.poseidon2_B_10_0[i] = rows[i].poseidon2_B_10_0; - polys.poseidon2_B_10_1[i] = rows[i].poseidon2_B_10_1; - polys.poseidon2_B_10_2[i] = rows[i].poseidon2_B_10_2; - polys.poseidon2_B_10_3[i] = rows[i].poseidon2_B_10_3; - polys.poseidon2_B_11_0[i] = rows[i].poseidon2_B_11_0; - polys.poseidon2_B_11_1[i] = rows[i].poseidon2_B_11_1; - polys.poseidon2_B_11_2[i] = rows[i].poseidon2_B_11_2; - polys.poseidon2_B_11_3[i] = rows[i].poseidon2_B_11_3; - polys.poseidon2_B_12_0[i] = rows[i].poseidon2_B_12_0; - polys.poseidon2_B_12_1[i] = rows[i].poseidon2_B_12_1; - polys.poseidon2_B_12_2[i] = rows[i].poseidon2_B_12_2; - polys.poseidon2_B_12_3[i] = rows[i].poseidon2_B_12_3; - polys.poseidon2_B_13_0[i] = rows[i].poseidon2_B_13_0; - polys.poseidon2_B_13_1[i] = rows[i].poseidon2_B_13_1; - polys.poseidon2_B_13_2[i] = rows[i].poseidon2_B_13_2; - polys.poseidon2_B_13_3[i] = rows[i].poseidon2_B_13_3; - polys.poseidon2_B_14_0[i] = rows[i].poseidon2_B_14_0; - polys.poseidon2_B_14_1[i] = rows[i].poseidon2_B_14_1; - polys.poseidon2_B_14_2[i] = rows[i].poseidon2_B_14_2; - polys.poseidon2_B_14_3[i] = rows[i].poseidon2_B_14_3; - polys.poseidon2_B_15_0[i] = rows[i].poseidon2_B_15_0; - polys.poseidon2_B_15_1[i] = rows[i].poseidon2_B_15_1; - polys.poseidon2_B_15_2[i] = rows[i].poseidon2_B_15_2; - polys.poseidon2_B_15_3[i] = rows[i].poseidon2_B_15_3; - polys.poseidon2_B_16_0[i] = rows[i].poseidon2_B_16_0; - polys.poseidon2_B_16_1[i] = rows[i].poseidon2_B_16_1; - polys.poseidon2_B_16_2[i] = rows[i].poseidon2_B_16_2; - polys.poseidon2_B_16_3[i] = rows[i].poseidon2_B_16_3; - polys.poseidon2_B_17_0[i] = rows[i].poseidon2_B_17_0; - polys.poseidon2_B_17_1[i] = rows[i].poseidon2_B_17_1; - polys.poseidon2_B_17_2[i] = rows[i].poseidon2_B_17_2; - polys.poseidon2_B_17_3[i] = rows[i].poseidon2_B_17_3; - polys.poseidon2_B_18_0[i] = rows[i].poseidon2_B_18_0; - polys.poseidon2_B_18_1[i] = rows[i].poseidon2_B_18_1; - polys.poseidon2_B_18_2[i] = rows[i].poseidon2_B_18_2; - polys.poseidon2_B_18_3[i] = rows[i].poseidon2_B_18_3; - polys.poseidon2_B_19_0[i] = rows[i].poseidon2_B_19_0; - polys.poseidon2_B_19_1[i] = rows[i].poseidon2_B_19_1; - polys.poseidon2_B_19_2[i] = rows[i].poseidon2_B_19_2; - polys.poseidon2_B_19_3[i] = rows[i].poseidon2_B_19_3; - polys.poseidon2_B_20_0[i] = rows[i].poseidon2_B_20_0; - polys.poseidon2_B_20_1[i] = rows[i].poseidon2_B_20_1; - polys.poseidon2_B_20_2[i] = rows[i].poseidon2_B_20_2; - polys.poseidon2_B_20_3[i] = rows[i].poseidon2_B_20_3; - polys.poseidon2_B_21_0[i] = rows[i].poseidon2_B_21_0; - polys.poseidon2_B_21_1[i] = rows[i].poseidon2_B_21_1; - polys.poseidon2_B_21_2[i] = rows[i].poseidon2_B_21_2; - polys.poseidon2_B_21_3[i] = rows[i].poseidon2_B_21_3; - polys.poseidon2_B_22_0[i] = rows[i].poseidon2_B_22_0; - polys.poseidon2_B_22_1[i] = rows[i].poseidon2_B_22_1; - polys.poseidon2_B_22_2[i] = rows[i].poseidon2_B_22_2; - polys.poseidon2_B_22_3[i] = rows[i].poseidon2_B_22_3; - polys.poseidon2_B_23_0[i] = rows[i].poseidon2_B_23_0; - polys.poseidon2_B_23_1[i] = rows[i].poseidon2_B_23_1; - polys.poseidon2_B_23_2[i] = rows[i].poseidon2_B_23_2; - polys.poseidon2_B_23_3[i] = rows[i].poseidon2_B_23_3; - polys.poseidon2_B_24_0[i] = rows[i].poseidon2_B_24_0; - polys.poseidon2_B_24_1[i] = rows[i].poseidon2_B_24_1; - polys.poseidon2_B_24_2[i] = rows[i].poseidon2_B_24_2; - polys.poseidon2_B_24_3[i] = rows[i].poseidon2_B_24_3; - polys.poseidon2_B_25_0[i] = rows[i].poseidon2_B_25_0; - polys.poseidon2_B_25_1[i] = rows[i].poseidon2_B_25_1; - polys.poseidon2_B_25_2[i] = rows[i].poseidon2_B_25_2; - polys.poseidon2_B_25_3[i] = rows[i].poseidon2_B_25_3; - polys.poseidon2_B_26_0[i] = rows[i].poseidon2_B_26_0; - polys.poseidon2_B_26_1[i] = rows[i].poseidon2_B_26_1; - polys.poseidon2_B_26_2[i] = rows[i].poseidon2_B_26_2; - polys.poseidon2_B_26_3[i] = rows[i].poseidon2_B_26_3; - polys.poseidon2_B_27_0[i] = rows[i].poseidon2_B_27_0; - polys.poseidon2_B_27_1[i] = rows[i].poseidon2_B_27_1; - polys.poseidon2_B_27_2[i] = rows[i].poseidon2_B_27_2; - polys.poseidon2_B_27_3[i] = rows[i].poseidon2_B_27_3; - polys.poseidon2_B_28_0[i] = rows[i].poseidon2_B_28_0; - polys.poseidon2_B_28_1[i] = rows[i].poseidon2_B_28_1; - polys.poseidon2_B_28_2[i] = rows[i].poseidon2_B_28_2; - polys.poseidon2_B_28_3[i] = rows[i].poseidon2_B_28_3; - polys.poseidon2_B_29_0[i] = rows[i].poseidon2_B_29_0; - polys.poseidon2_B_29_1[i] = rows[i].poseidon2_B_29_1; - polys.poseidon2_B_29_2[i] = rows[i].poseidon2_B_29_2; - polys.poseidon2_B_29_3[i] = rows[i].poseidon2_B_29_3; - polys.poseidon2_B_30_0[i] = rows[i].poseidon2_B_30_0; - polys.poseidon2_B_30_1[i] = rows[i].poseidon2_B_30_1; - polys.poseidon2_B_30_2[i] = rows[i].poseidon2_B_30_2; - polys.poseidon2_B_30_3[i] = rows[i].poseidon2_B_30_3; - polys.poseidon2_B_31_0[i] = rows[i].poseidon2_B_31_0; - polys.poseidon2_B_31_1[i] = rows[i].poseidon2_B_31_1; - polys.poseidon2_B_31_2[i] = rows[i].poseidon2_B_31_2; - polys.poseidon2_B_31_3[i] = rows[i].poseidon2_B_31_3; - polys.poseidon2_B_32_0[i] = rows[i].poseidon2_B_32_0; - polys.poseidon2_B_32_1[i] = rows[i].poseidon2_B_32_1; - polys.poseidon2_B_32_2[i] = rows[i].poseidon2_B_32_2; - polys.poseidon2_B_32_3[i] = rows[i].poseidon2_B_32_3; - polys.poseidon2_B_33_0[i] = rows[i].poseidon2_B_33_0; - polys.poseidon2_B_33_1[i] = rows[i].poseidon2_B_33_1; - polys.poseidon2_B_33_2[i] = rows[i].poseidon2_B_33_2; - polys.poseidon2_B_33_3[i] = rows[i].poseidon2_B_33_3; - polys.poseidon2_B_34_0[i] = rows[i].poseidon2_B_34_0; - polys.poseidon2_B_34_1[i] = rows[i].poseidon2_B_34_1; - polys.poseidon2_B_34_2[i] = rows[i].poseidon2_B_34_2; - polys.poseidon2_B_34_3[i] = rows[i].poseidon2_B_34_3; - polys.poseidon2_B_35_0[i] = rows[i].poseidon2_B_35_0; - polys.poseidon2_B_35_1[i] = rows[i].poseidon2_B_35_1; - polys.poseidon2_B_35_2[i] = rows[i].poseidon2_B_35_2; - polys.poseidon2_B_35_3[i] = rows[i].poseidon2_B_35_3; - polys.poseidon2_B_36_0[i] = rows[i].poseidon2_B_36_0; - polys.poseidon2_B_36_1[i] = rows[i].poseidon2_B_36_1; - polys.poseidon2_B_36_2[i] = rows[i].poseidon2_B_36_2; - polys.poseidon2_B_36_3[i] = rows[i].poseidon2_B_36_3; - polys.poseidon2_B_37_0[i] = rows[i].poseidon2_B_37_0; - polys.poseidon2_B_37_1[i] = rows[i].poseidon2_B_37_1; - polys.poseidon2_B_37_2[i] = rows[i].poseidon2_B_37_2; - polys.poseidon2_B_37_3[i] = rows[i].poseidon2_B_37_3; - polys.poseidon2_B_38_0[i] = rows[i].poseidon2_B_38_0; - polys.poseidon2_B_38_1[i] = rows[i].poseidon2_B_38_1; - polys.poseidon2_B_38_2[i] = rows[i].poseidon2_B_38_2; - polys.poseidon2_B_38_3[i] = rows[i].poseidon2_B_38_3; - polys.poseidon2_B_39_0[i] = rows[i].poseidon2_B_39_0; - polys.poseidon2_B_39_1[i] = rows[i].poseidon2_B_39_1; - polys.poseidon2_B_39_2[i] = rows[i].poseidon2_B_39_2; - polys.poseidon2_B_39_3[i] = rows[i].poseidon2_B_39_3; - polys.poseidon2_B_40_0[i] = rows[i].poseidon2_B_40_0; - polys.poseidon2_B_40_1[i] = rows[i].poseidon2_B_40_1; - polys.poseidon2_B_40_2[i] = rows[i].poseidon2_B_40_2; - polys.poseidon2_B_40_3[i] = rows[i].poseidon2_B_40_3; - polys.poseidon2_B_41_0[i] = rows[i].poseidon2_B_41_0; - polys.poseidon2_B_41_1[i] = rows[i].poseidon2_B_41_1; - polys.poseidon2_B_41_2[i] = rows[i].poseidon2_B_41_2; - polys.poseidon2_B_41_3[i] = rows[i].poseidon2_B_41_3; - polys.poseidon2_B_42_0[i] = rows[i].poseidon2_B_42_0; - polys.poseidon2_B_42_1[i] = rows[i].poseidon2_B_42_1; - polys.poseidon2_B_42_2[i] = rows[i].poseidon2_B_42_2; - polys.poseidon2_B_42_3[i] = rows[i].poseidon2_B_42_3; - polys.poseidon2_B_43_0[i] = rows[i].poseidon2_B_43_0; - polys.poseidon2_B_43_1[i] = rows[i].poseidon2_B_43_1; - polys.poseidon2_B_43_2[i] = rows[i].poseidon2_B_43_2; - polys.poseidon2_B_43_3[i] = rows[i].poseidon2_B_43_3; - polys.poseidon2_B_44_0[i] = rows[i].poseidon2_B_44_0; - polys.poseidon2_B_44_1[i] = rows[i].poseidon2_B_44_1; - polys.poseidon2_B_44_2[i] = rows[i].poseidon2_B_44_2; - polys.poseidon2_B_44_3[i] = rows[i].poseidon2_B_44_3; - polys.poseidon2_B_45_0[i] = rows[i].poseidon2_B_45_0; - polys.poseidon2_B_45_1[i] = rows[i].poseidon2_B_45_1; - polys.poseidon2_B_45_2[i] = rows[i].poseidon2_B_45_2; - polys.poseidon2_B_45_3[i] = rows[i].poseidon2_B_45_3; - polys.poseidon2_B_46_0[i] = rows[i].poseidon2_B_46_0; - polys.poseidon2_B_46_1[i] = rows[i].poseidon2_B_46_1; - polys.poseidon2_B_46_2[i] = rows[i].poseidon2_B_46_2; - polys.poseidon2_B_46_3[i] = rows[i].poseidon2_B_46_3; - polys.poseidon2_B_47_0[i] = rows[i].poseidon2_B_47_0; - polys.poseidon2_B_47_1[i] = rows[i].poseidon2_B_47_1; - polys.poseidon2_B_47_2[i] = rows[i].poseidon2_B_47_2; - polys.poseidon2_B_47_3[i] = rows[i].poseidon2_B_47_3; - polys.poseidon2_B_48_0[i] = rows[i].poseidon2_B_48_0; - polys.poseidon2_B_48_1[i] = rows[i].poseidon2_B_48_1; - polys.poseidon2_B_48_2[i] = rows[i].poseidon2_B_48_2; - polys.poseidon2_B_48_3[i] = rows[i].poseidon2_B_48_3; - polys.poseidon2_B_49_0[i] = rows[i].poseidon2_B_49_0; - polys.poseidon2_B_49_1[i] = rows[i].poseidon2_B_49_1; - polys.poseidon2_B_49_2[i] = rows[i].poseidon2_B_49_2; - polys.poseidon2_B_49_3[i] = rows[i].poseidon2_B_49_3; - polys.poseidon2_B_4_0[i] = rows[i].poseidon2_B_4_0; - polys.poseidon2_B_4_1[i] = rows[i].poseidon2_B_4_1; - polys.poseidon2_B_4_2[i] = rows[i].poseidon2_B_4_2; - polys.poseidon2_B_4_3[i] = rows[i].poseidon2_B_4_3; - polys.poseidon2_B_50_0[i] = rows[i].poseidon2_B_50_0; - polys.poseidon2_B_50_1[i] = rows[i].poseidon2_B_50_1; - polys.poseidon2_B_50_2[i] = rows[i].poseidon2_B_50_2; - polys.poseidon2_B_50_3[i] = rows[i].poseidon2_B_50_3; - polys.poseidon2_B_51_0[i] = rows[i].poseidon2_B_51_0; - polys.poseidon2_B_51_1[i] = rows[i].poseidon2_B_51_1; - polys.poseidon2_B_51_2[i] = rows[i].poseidon2_B_51_2; - polys.poseidon2_B_51_3[i] = rows[i].poseidon2_B_51_3; - polys.poseidon2_B_52_0[i] = rows[i].poseidon2_B_52_0; - polys.poseidon2_B_52_1[i] = rows[i].poseidon2_B_52_1; - polys.poseidon2_B_52_2[i] = rows[i].poseidon2_B_52_2; - polys.poseidon2_B_52_3[i] = rows[i].poseidon2_B_52_3; - polys.poseidon2_B_53_0[i] = rows[i].poseidon2_B_53_0; - polys.poseidon2_B_53_1[i] = rows[i].poseidon2_B_53_1; - polys.poseidon2_B_53_2[i] = rows[i].poseidon2_B_53_2; - polys.poseidon2_B_53_3[i] = rows[i].poseidon2_B_53_3; - polys.poseidon2_B_54_0[i] = rows[i].poseidon2_B_54_0; - polys.poseidon2_B_54_1[i] = rows[i].poseidon2_B_54_1; - polys.poseidon2_B_54_2[i] = rows[i].poseidon2_B_54_2; - polys.poseidon2_B_54_3[i] = rows[i].poseidon2_B_54_3; - polys.poseidon2_B_55_0[i] = rows[i].poseidon2_B_55_0; - polys.poseidon2_B_55_1[i] = rows[i].poseidon2_B_55_1; - polys.poseidon2_B_55_2[i] = rows[i].poseidon2_B_55_2; - polys.poseidon2_B_55_3[i] = rows[i].poseidon2_B_55_3; - polys.poseidon2_B_56_0[i] = rows[i].poseidon2_B_56_0; - polys.poseidon2_B_56_1[i] = rows[i].poseidon2_B_56_1; - polys.poseidon2_B_56_2[i] = rows[i].poseidon2_B_56_2; - polys.poseidon2_B_56_3[i] = rows[i].poseidon2_B_56_3; - polys.poseidon2_B_57_0[i] = rows[i].poseidon2_B_57_0; - polys.poseidon2_B_57_1[i] = rows[i].poseidon2_B_57_1; - polys.poseidon2_B_57_2[i] = rows[i].poseidon2_B_57_2; - polys.poseidon2_B_57_3[i] = rows[i].poseidon2_B_57_3; - polys.poseidon2_B_58_0[i] = rows[i].poseidon2_B_58_0; - polys.poseidon2_B_58_1[i] = rows[i].poseidon2_B_58_1; - polys.poseidon2_B_58_2[i] = rows[i].poseidon2_B_58_2; - polys.poseidon2_B_58_3[i] = rows[i].poseidon2_B_58_3; - polys.poseidon2_B_59_0[i] = rows[i].poseidon2_B_59_0; - polys.poseidon2_B_59_1[i] = rows[i].poseidon2_B_59_1; - polys.poseidon2_B_59_2[i] = rows[i].poseidon2_B_59_2; - polys.poseidon2_B_59_3[i] = rows[i].poseidon2_B_59_3; - polys.poseidon2_B_5_0[i] = rows[i].poseidon2_B_5_0; - polys.poseidon2_B_5_1[i] = rows[i].poseidon2_B_5_1; - polys.poseidon2_B_5_2[i] = rows[i].poseidon2_B_5_2; - polys.poseidon2_B_5_3[i] = rows[i].poseidon2_B_5_3; - polys.poseidon2_B_6_0[i] = rows[i].poseidon2_B_6_0; - polys.poseidon2_B_6_1[i] = rows[i].poseidon2_B_6_1; - polys.poseidon2_B_6_2[i] = rows[i].poseidon2_B_6_2; - polys.poseidon2_B_6_3[i] = rows[i].poseidon2_B_6_3; - polys.poseidon2_B_7_0[i] = rows[i].poseidon2_B_7_0; - polys.poseidon2_B_7_1[i] = rows[i].poseidon2_B_7_1; - polys.poseidon2_B_7_2[i] = rows[i].poseidon2_B_7_2; - polys.poseidon2_B_7_3[i] = rows[i].poseidon2_B_7_3; - polys.poseidon2_B_8_0[i] = rows[i].poseidon2_B_8_0; - polys.poseidon2_B_8_1[i] = rows[i].poseidon2_B_8_1; - polys.poseidon2_B_8_2[i] = rows[i].poseidon2_B_8_2; - polys.poseidon2_B_8_3[i] = rows[i].poseidon2_B_8_3; - polys.poseidon2_B_9_0[i] = rows[i].poseidon2_B_9_0; - polys.poseidon2_B_9_1[i] = rows[i].poseidon2_B_9_1; - polys.poseidon2_B_9_2[i] = rows[i].poseidon2_B_9_2; - polys.poseidon2_B_9_3[i] = rows[i].poseidon2_B_9_3; - polys.poseidon2_EXT_LAYER_4[i] = rows[i].poseidon2_EXT_LAYER_4; - polys.poseidon2_EXT_LAYER_5[i] = rows[i].poseidon2_EXT_LAYER_5; - polys.poseidon2_EXT_LAYER_6[i] = rows[i].poseidon2_EXT_LAYER_6; - polys.poseidon2_EXT_LAYER_7[i] = rows[i].poseidon2_EXT_LAYER_7; - polys.poseidon2_T_0_4[i] = rows[i].poseidon2_T_0_4; - polys.poseidon2_T_0_5[i] = rows[i].poseidon2_T_0_5; - polys.poseidon2_T_0_6[i] = rows[i].poseidon2_T_0_6; - polys.poseidon2_T_0_7[i] = rows[i].poseidon2_T_0_7; - polys.poseidon2_T_1_4[i] = rows[i].poseidon2_T_1_4; - polys.poseidon2_T_1_5[i] = rows[i].poseidon2_T_1_5; - polys.poseidon2_T_1_6[i] = rows[i].poseidon2_T_1_6; - polys.poseidon2_T_1_7[i] = rows[i].poseidon2_T_1_7; - polys.poseidon2_T_2_4[i] = rows[i].poseidon2_T_2_4; - polys.poseidon2_T_2_5[i] = rows[i].poseidon2_T_2_5; - polys.poseidon2_T_2_6[i] = rows[i].poseidon2_T_2_6; - polys.poseidon2_T_2_7[i] = rows[i].poseidon2_T_2_7; - polys.poseidon2_T_3_4[i] = rows[i].poseidon2_T_3_4; - polys.poseidon2_T_3_5[i] = rows[i].poseidon2_T_3_5; - polys.poseidon2_T_3_6[i] = rows[i].poseidon2_T_3_6; - polys.poseidon2_T_3_7[i] = rows[i].poseidon2_T_3_7; - polys.poseidon2_T_60_4[i] = rows[i].poseidon2_T_60_4; - polys.poseidon2_T_60_5[i] = rows[i].poseidon2_T_60_5; - polys.poseidon2_T_60_6[i] = rows[i].poseidon2_T_60_6; - polys.poseidon2_T_60_7[i] = rows[i].poseidon2_T_60_7; - polys.poseidon2_T_61_4[i] = rows[i].poseidon2_T_61_4; - polys.poseidon2_T_61_5[i] = rows[i].poseidon2_T_61_5; - polys.poseidon2_T_61_6[i] = rows[i].poseidon2_T_61_6; - polys.poseidon2_T_61_7[i] = rows[i].poseidon2_T_61_7; - polys.poseidon2_T_62_4[i] = rows[i].poseidon2_T_62_4; - polys.poseidon2_T_62_5[i] = rows[i].poseidon2_T_62_5; - polys.poseidon2_T_62_6[i] = rows[i].poseidon2_T_62_6; - polys.poseidon2_T_62_7[i] = rows[i].poseidon2_T_62_7; - polys.poseidon2_T_63_4[i] = rows[i].poseidon2_T_63_4; - polys.poseidon2_T_63_5[i] = rows[i].poseidon2_T_63_5; - polys.poseidon2_T_63_6[i] = rows[i].poseidon2_T_63_6; - polys.poseidon2_T_63_7[i] = rows[i].poseidon2_T_63_7; - polys.poseidon2_a_0[i] = rows[i].poseidon2_a_0; - polys.poseidon2_a_1[i] = rows[i].poseidon2_a_1; - polys.poseidon2_a_2[i] = rows[i].poseidon2_a_2; - polys.poseidon2_a_3[i] = rows[i].poseidon2_a_3; - polys.poseidon2_b_0[i] = rows[i].poseidon2_b_0; - polys.poseidon2_b_1[i] = rows[i].poseidon2_b_1; - polys.poseidon2_b_2[i] = rows[i].poseidon2_b_2; - polys.poseidon2_b_3[i] = rows[i].poseidon2_b_3; - polys.poseidon2_clk[i] = rows[i].poseidon2_clk; - polys.poseidon2_input_addr[i] = rows[i].poseidon2_input_addr; - polys.poseidon2_mem_addr_read_a[i] = rows[i].poseidon2_mem_addr_read_a; - polys.poseidon2_mem_addr_read_b[i] = rows[i].poseidon2_mem_addr_read_b; - polys.poseidon2_mem_addr_read_c[i] = rows[i].poseidon2_mem_addr_read_c; - polys.poseidon2_mem_addr_read_d[i] = rows[i].poseidon2_mem_addr_read_d; - polys.poseidon2_mem_addr_write_a[i] = rows[i].poseidon2_mem_addr_write_a; - polys.poseidon2_mem_addr_write_b[i] = rows[i].poseidon2_mem_addr_write_b; - polys.poseidon2_mem_addr_write_c[i] = rows[i].poseidon2_mem_addr_write_c; - polys.poseidon2_mem_addr_write_d[i] = rows[i].poseidon2_mem_addr_write_d; - polys.poseidon2_output_addr[i] = rows[i].poseidon2_output_addr; - polys.poseidon2_sel_poseidon_perm[i] = rows[i].poseidon2_sel_poseidon_perm; - polys.range_check_alu_rng_chk[i] = rows[i].range_check_alu_rng_chk; - polys.range_check_clk[i] = rows[i].range_check_clk; - polys.range_check_cmp_hi_bits_rng_chk[i] = rows[i].range_check_cmp_hi_bits_rng_chk; - polys.range_check_cmp_lo_bits_rng_chk[i] = rows[i].range_check_cmp_lo_bits_rng_chk; - polys.range_check_dyn_diff[i] = rows[i].range_check_dyn_diff; - polys.range_check_dyn_rng_chk_bits[i] = rows[i].range_check_dyn_rng_chk_bits; - polys.range_check_dyn_rng_chk_pow_2[i] = rows[i].range_check_dyn_rng_chk_pow_2; - polys.range_check_gas_da_rng_chk[i] = rows[i].range_check_gas_da_rng_chk; - polys.range_check_gas_l2_rng_chk[i] = rows[i].range_check_gas_l2_rng_chk; - polys.range_check_is_lte_u112[i] = rows[i].range_check_is_lte_u112; - polys.range_check_is_lte_u128[i] = rows[i].range_check_is_lte_u128; - polys.range_check_is_lte_u16[i] = rows[i].range_check_is_lte_u16; - polys.range_check_is_lte_u32[i] = rows[i].range_check_is_lte_u32; - polys.range_check_is_lte_u48[i] = rows[i].range_check_is_lte_u48; - polys.range_check_is_lte_u64[i] = rows[i].range_check_is_lte_u64; - polys.range_check_is_lte_u80[i] = rows[i].range_check_is_lte_u80; - polys.range_check_is_lte_u96[i] = rows[i].range_check_is_lte_u96; - polys.range_check_mem_rng_chk[i] = rows[i].range_check_mem_rng_chk; - polys.range_check_rng_chk_bits[i] = rows[i].range_check_rng_chk_bits; - polys.range_check_sel_lookup_0[i] = rows[i].range_check_sel_lookup_0; - polys.range_check_sel_lookup_1[i] = rows[i].range_check_sel_lookup_1; - polys.range_check_sel_lookup_2[i] = rows[i].range_check_sel_lookup_2; - polys.range_check_sel_lookup_3[i] = rows[i].range_check_sel_lookup_3; - polys.range_check_sel_lookup_4[i] = rows[i].range_check_sel_lookup_4; - polys.range_check_sel_lookup_5[i] = rows[i].range_check_sel_lookup_5; - polys.range_check_sel_lookup_6[i] = rows[i].range_check_sel_lookup_6; - polys.range_check_sel_rng_chk[i] = rows[i].range_check_sel_rng_chk; - polys.range_check_u16_r0[i] = rows[i].range_check_u16_r0; - polys.range_check_u16_r1[i] = rows[i].range_check_u16_r1; - polys.range_check_u16_r2[i] = rows[i].range_check_u16_r2; - polys.range_check_u16_r3[i] = rows[i].range_check_u16_r3; - polys.range_check_u16_r4[i] = rows[i].range_check_u16_r4; - polys.range_check_u16_r5[i] = rows[i].range_check_u16_r5; - polys.range_check_u16_r6[i] = rows[i].range_check_u16_r6; - polys.range_check_u16_r7[i] = rows[i].range_check_u16_r7; - polys.range_check_value[i] = rows[i].range_check_value; - polys.sha256_clk[i] = rows[i].sha256_clk; - polys.sha256_input[i] = rows[i].sha256_input; - polys.sha256_output[i] = rows[i].sha256_output; - polys.sha256_sel_sha256_compression[i] = rows[i].sha256_sel_sha256_compression; - polys.sha256_state[i] = rows[i].sha256_state; - polys.slice_addr[i] = rows[i].slice_addr; - polys.slice_clk[i] = rows[i].slice_clk; - polys.slice_cnt[i] = rows[i].slice_cnt; - polys.slice_col_offset[i] = rows[i].slice_col_offset; - polys.slice_one_min_inv[i] = rows[i].slice_one_min_inv; - polys.slice_sel_cd_cpy[i] = rows[i].slice_sel_cd_cpy; - polys.slice_sel_mem_active[i] = rows[i].slice_sel_mem_active; - polys.slice_sel_return[i] = rows[i].slice_sel_return; - polys.slice_sel_start[i] = rows[i].slice_sel_start; - polys.slice_space_id[i] = rows[i].slice_space_id; - polys.slice_val[i] = rows[i].slice_val; - polys.lookup_rng_chk_pow_2_counts[i] = rows[i].lookup_rng_chk_pow_2_counts; - polys.lookup_rng_chk_diff_counts[i] = rows[i].lookup_rng_chk_diff_counts; - polys.lookup_rng_chk_0_counts[i] = rows[i].lookup_rng_chk_0_counts; - polys.lookup_rng_chk_1_counts[i] = rows[i].lookup_rng_chk_1_counts; - polys.lookup_rng_chk_2_counts[i] = rows[i].lookup_rng_chk_2_counts; - polys.lookup_rng_chk_3_counts[i] = rows[i].lookup_rng_chk_3_counts; - polys.lookup_rng_chk_4_counts[i] = rows[i].lookup_rng_chk_4_counts; - polys.lookup_rng_chk_5_counts[i] = rows[i].lookup_rng_chk_5_counts; - polys.lookup_rng_chk_6_counts[i] = rows[i].lookup_rng_chk_6_counts; - polys.lookup_rng_chk_7_counts[i] = rows[i].lookup_rng_chk_7_counts; - polys.lookup_pow_2_0_counts[i] = rows[i].lookup_pow_2_0_counts; - polys.lookup_pow_2_1_counts[i] = rows[i].lookup_pow_2_1_counts; - polys.lookup_byte_lengths_counts[i] = rows[i].lookup_byte_lengths_counts; - polys.lookup_byte_operations_counts[i] = rows[i].lookup_byte_operations_counts; - polys.lookup_opcode_gas_counts[i] = rows[i].lookup_opcode_gas_counts; - polys.kernel_output_lookup_counts[i] = rows[i].kernel_output_lookup_counts; - polys.lookup_into_kernel_counts[i] = rows[i].lookup_into_kernel_counts; - polys.lookup_cd_value_counts[i] = rows[i].lookup_cd_value_counts; - polys.lookup_ret_value_counts[i] = rows[i].lookup_ret_value_counts; - polys.incl_main_tag_err_counts[i] = rows[i].incl_main_tag_err_counts; - polys.incl_mem_tag_err_counts[i] = rows[i].incl_mem_tag_err_counts; + polys.byte_lookup_sel_bin.set_if_valid_index(i, rows[i].byte_lookup_sel_bin); + polys.byte_lookup_table_byte_lengths.set_if_valid_index(i, rows[i].byte_lookup_table_byte_lengths); + polys.byte_lookup_table_in_tags.set_if_valid_index(i, rows[i].byte_lookup_table_in_tags); + polys.byte_lookup_table_input_a.set_if_valid_index(i, rows[i].byte_lookup_table_input_a); + polys.byte_lookup_table_input_b.set_if_valid_index(i, rows[i].byte_lookup_table_input_b); + polys.byte_lookup_table_op_id.set_if_valid_index(i, rows[i].byte_lookup_table_op_id); + polys.byte_lookup_table_output.set_if_valid_index(i, rows[i].byte_lookup_table_output); + polys.gas_base_da_gas_fixed_table.set_if_valid_index(i, rows[i].gas_base_da_gas_fixed_table); + polys.gas_base_l2_gas_fixed_table.set_if_valid_index(i, rows[i].gas_base_l2_gas_fixed_table); + polys.gas_dyn_da_gas_fixed_table.set_if_valid_index(i, rows[i].gas_dyn_da_gas_fixed_table); + polys.gas_dyn_l2_gas_fixed_table.set_if_valid_index(i, rows[i].gas_dyn_l2_gas_fixed_table); + polys.gas_sel_gas_cost.set_if_valid_index(i, rows[i].gas_sel_gas_cost); + polys.main_clk.set_if_valid_index(i, rows[i].main_clk); + polys.main_sel_first.set_if_valid_index(i, rows[i].main_sel_first); + polys.main_zeroes.set_if_valid_index(i, rows[i].main_zeroes); + polys.powers_power_of_2.set_if_valid_index(i, rows[i].powers_power_of_2); + polys.main_kernel_inputs.set_if_valid_index(i, rows[i].main_kernel_inputs); + polys.main_kernel_value_out.set_if_valid_index(i, rows[i].main_kernel_value_out); + polys.main_kernel_side_effect_out.set_if_valid_index(i, rows[i].main_kernel_side_effect_out); + polys.main_kernel_metadata_out.set_if_valid_index(i, rows[i].main_kernel_metadata_out); + polys.main_calldata.set_if_valid_index(i, rows[i].main_calldata); + polys.main_returndata.set_if_valid_index(i, rows[i].main_returndata); + polys.alu_a_hi.set_if_valid_index(i, rows[i].alu_a_hi); + polys.alu_a_lo.set_if_valid_index(i, rows[i].alu_a_lo); + polys.alu_b_hi.set_if_valid_index(i, rows[i].alu_b_hi); + polys.alu_b_lo.set_if_valid_index(i, rows[i].alu_b_lo); + polys.alu_b_pow.set_if_valid_index(i, rows[i].alu_b_pow); + polys.alu_c_hi.set_if_valid_index(i, rows[i].alu_c_hi); + polys.alu_c_lo.set_if_valid_index(i, rows[i].alu_c_lo); + polys.alu_cf.set_if_valid_index(i, rows[i].alu_cf); + polys.alu_clk.set_if_valid_index(i, rows[i].alu_clk); + polys.alu_cmp_gadget_gt.set_if_valid_index(i, rows[i].alu_cmp_gadget_gt); + polys.alu_cmp_gadget_input_a.set_if_valid_index(i, rows[i].alu_cmp_gadget_input_a); + polys.alu_cmp_gadget_input_b.set_if_valid_index(i, rows[i].alu_cmp_gadget_input_b); + polys.alu_cmp_gadget_result.set_if_valid_index(i, rows[i].alu_cmp_gadget_result); + polys.alu_cmp_gadget_sel.set_if_valid_index(i, rows[i].alu_cmp_gadget_sel); + polys.alu_ff_tag.set_if_valid_index(i, rows[i].alu_ff_tag); + polys.alu_ia.set_if_valid_index(i, rows[i].alu_ia); + polys.alu_ib.set_if_valid_index(i, rows[i].alu_ib); + polys.alu_ic.set_if_valid_index(i, rows[i].alu_ic); + polys.alu_in_tag.set_if_valid_index(i, rows[i].alu_in_tag); + polys.alu_max_bits_sub_b_bits.set_if_valid_index(i, rows[i].alu_max_bits_sub_b_bits); + polys.alu_max_bits_sub_b_pow.set_if_valid_index(i, rows[i].alu_max_bits_sub_b_pow); + polys.alu_op_add.set_if_valid_index(i, rows[i].alu_op_add); + polys.alu_op_cast.set_if_valid_index(i, rows[i].alu_op_cast); + polys.alu_op_div.set_if_valid_index(i, rows[i].alu_op_div); + polys.alu_op_eq.set_if_valid_index(i, rows[i].alu_op_eq); + polys.alu_op_lt.set_if_valid_index(i, rows[i].alu_op_lt); + polys.alu_op_lte.set_if_valid_index(i, rows[i].alu_op_lte); + polys.alu_op_mul.set_if_valid_index(i, rows[i].alu_op_mul); + polys.alu_op_not.set_if_valid_index(i, rows[i].alu_op_not); + polys.alu_op_shl.set_if_valid_index(i, rows[i].alu_op_shl); + polys.alu_op_shr.set_if_valid_index(i, rows[i].alu_op_shr); + polys.alu_op_sub.set_if_valid_index(i, rows[i].alu_op_sub); + polys.alu_partial_prod_hi.set_if_valid_index(i, rows[i].alu_partial_prod_hi); + polys.alu_partial_prod_lo.set_if_valid_index(i, rows[i].alu_partial_prod_lo); + polys.alu_range_check_input_value.set_if_valid_index(i, rows[i].alu_range_check_input_value); + polys.alu_range_check_num_bits.set_if_valid_index(i, rows[i].alu_range_check_num_bits); + polys.alu_range_check_sel.set_if_valid_index(i, rows[i].alu_range_check_sel); + polys.alu_remainder.set_if_valid_index(i, rows[i].alu_remainder); + polys.alu_sel_alu.set_if_valid_index(i, rows[i].alu_sel_alu); + polys.alu_sel_cmp.set_if_valid_index(i, rows[i].alu_sel_cmp); + polys.alu_sel_shift_which.set_if_valid_index(i, rows[i].alu_sel_shift_which); + polys.alu_u128_tag.set_if_valid_index(i, rows[i].alu_u128_tag); + polys.alu_u16_tag.set_if_valid_index(i, rows[i].alu_u16_tag); + polys.alu_u32_tag.set_if_valid_index(i, rows[i].alu_u32_tag); + polys.alu_u64_tag.set_if_valid_index(i, rows[i].alu_u64_tag); + polys.alu_u8_tag.set_if_valid_index(i, rows[i].alu_u8_tag); + polys.alu_zero_shift.set_if_valid_index(i, rows[i].alu_zero_shift); + polys.binary_acc_ia.set_if_valid_index(i, rows[i].binary_acc_ia); + polys.binary_acc_ib.set_if_valid_index(i, rows[i].binary_acc_ib); + polys.binary_acc_ic.set_if_valid_index(i, rows[i].binary_acc_ic); + polys.binary_clk.set_if_valid_index(i, rows[i].binary_clk); + polys.binary_ia_bytes.set_if_valid_index(i, rows[i].binary_ia_bytes); + polys.binary_ib_bytes.set_if_valid_index(i, rows[i].binary_ib_bytes); + polys.binary_ic_bytes.set_if_valid_index(i, rows[i].binary_ic_bytes); + polys.binary_in_tag.set_if_valid_index(i, rows[i].binary_in_tag); + polys.binary_mem_tag_ctr.set_if_valid_index(i, rows[i].binary_mem_tag_ctr); + polys.binary_mem_tag_ctr_inv.set_if_valid_index(i, rows[i].binary_mem_tag_ctr_inv); + polys.binary_op_id.set_if_valid_index(i, rows[i].binary_op_id); + polys.binary_sel_bin.set_if_valid_index(i, rows[i].binary_sel_bin); + polys.binary_start.set_if_valid_index(i, rows[i].binary_start); + polys.cmp_a_hi.set_if_valid_index(i, rows[i].cmp_a_hi); + polys.cmp_a_lo.set_if_valid_index(i, rows[i].cmp_a_lo); + polys.cmp_b_hi.set_if_valid_index(i, rows[i].cmp_b_hi); + polys.cmp_b_lo.set_if_valid_index(i, rows[i].cmp_b_lo); + polys.cmp_borrow.set_if_valid_index(i, rows[i].cmp_borrow); + polys.cmp_clk.set_if_valid_index(i, rows[i].cmp_clk); + polys.cmp_cmp_rng_ctr.set_if_valid_index(i, rows[i].cmp_cmp_rng_ctr); + polys.cmp_input_a.set_if_valid_index(i, rows[i].cmp_input_a); + polys.cmp_input_b.set_if_valid_index(i, rows[i].cmp_input_b); + polys.cmp_op_eq.set_if_valid_index(i, rows[i].cmp_op_eq); + polys.cmp_op_eq_diff_inv.set_if_valid_index(i, rows[i].cmp_op_eq_diff_inv); + polys.cmp_op_gt.set_if_valid_index(i, rows[i].cmp_op_gt); + polys.cmp_p_a_borrow.set_if_valid_index(i, rows[i].cmp_p_a_borrow); + polys.cmp_p_b_borrow.set_if_valid_index(i, rows[i].cmp_p_b_borrow); + polys.cmp_p_sub_a_hi.set_if_valid_index(i, rows[i].cmp_p_sub_a_hi); + polys.cmp_p_sub_a_lo.set_if_valid_index(i, rows[i].cmp_p_sub_a_lo); + polys.cmp_p_sub_b_hi.set_if_valid_index(i, rows[i].cmp_p_sub_b_hi); + polys.cmp_p_sub_b_lo.set_if_valid_index(i, rows[i].cmp_p_sub_b_lo); + polys.cmp_range_chk_clk.set_if_valid_index(i, rows[i].cmp_range_chk_clk); + polys.cmp_res_hi.set_if_valid_index(i, rows[i].cmp_res_hi); + polys.cmp_res_lo.set_if_valid_index(i, rows[i].cmp_res_lo); + polys.cmp_result.set_if_valid_index(i, rows[i].cmp_result); + polys.cmp_sel_cmp.set_if_valid_index(i, rows[i].cmp_sel_cmp); + polys.cmp_sel_rng_chk.set_if_valid_index(i, rows[i].cmp_sel_rng_chk); + polys.cmp_shift_sel.set_if_valid_index(i, rows[i].cmp_shift_sel); + polys.conversion_clk.set_if_valid_index(i, rows[i].conversion_clk); + polys.conversion_input.set_if_valid_index(i, rows[i].conversion_input); + polys.conversion_num_limbs.set_if_valid_index(i, rows[i].conversion_num_limbs); + polys.conversion_radix.set_if_valid_index(i, rows[i].conversion_radix); + polys.conversion_sel_to_radix_le.set_if_valid_index(i, rows[i].conversion_sel_to_radix_le); + polys.keccakf1600_clk.set_if_valid_index(i, rows[i].keccakf1600_clk); + polys.keccakf1600_input.set_if_valid_index(i, rows[i].keccakf1600_input); + polys.keccakf1600_output.set_if_valid_index(i, rows[i].keccakf1600_output); + polys.keccakf1600_sel_keccakf1600.set_if_valid_index(i, rows[i].keccakf1600_sel_keccakf1600); + polys.main_abs_da_rem_gas.set_if_valid_index(i, rows[i].main_abs_da_rem_gas); + polys.main_abs_l2_rem_gas.set_if_valid_index(i, rows[i].main_abs_l2_rem_gas); + polys.main_alu_in_tag.set_if_valid_index(i, rows[i].main_alu_in_tag); + polys.main_base_da_gas_op_cost.set_if_valid_index(i, rows[i].main_base_da_gas_op_cost); + polys.main_base_l2_gas_op_cost.set_if_valid_index(i, rows[i].main_base_l2_gas_op_cost); + polys.main_bin_op_id.set_if_valid_index(i, rows[i].main_bin_op_id); + polys.main_call_ptr.set_if_valid_index(i, rows[i].main_call_ptr); + polys.main_da_gas_remaining.set_if_valid_index(i, rows[i].main_da_gas_remaining); + polys.main_da_out_of_gas.set_if_valid_index(i, rows[i].main_da_out_of_gas); + polys.main_dyn_da_gas_op_cost.set_if_valid_index(i, rows[i].main_dyn_da_gas_op_cost); + polys.main_dyn_gas_multiplier.set_if_valid_index(i, rows[i].main_dyn_gas_multiplier); + polys.main_dyn_l2_gas_op_cost.set_if_valid_index(i, rows[i].main_dyn_l2_gas_op_cost); + polys.main_emit_l2_to_l1_msg_write_offset.set_if_valid_index(i, rows[i].main_emit_l2_to_l1_msg_write_offset); + polys.main_emit_note_hash_write_offset.set_if_valid_index(i, rows[i].main_emit_note_hash_write_offset); + polys.main_emit_nullifier_write_offset.set_if_valid_index(i, rows[i].main_emit_nullifier_write_offset); + polys.main_emit_unencrypted_log_write_offset.set_if_valid_index(i, + rows[i].main_emit_unencrypted_log_write_offset); + polys.main_ia.set_if_valid_index(i, rows[i].main_ia); + polys.main_ib.set_if_valid_index(i, rows[i].main_ib); + polys.main_ic.set_if_valid_index(i, rows[i].main_ic); + polys.main_id.set_if_valid_index(i, rows[i].main_id); + polys.main_id_zero.set_if_valid_index(i, rows[i].main_id_zero); + polys.main_ind_addr_a.set_if_valid_index(i, rows[i].main_ind_addr_a); + polys.main_ind_addr_b.set_if_valid_index(i, rows[i].main_ind_addr_b); + polys.main_ind_addr_c.set_if_valid_index(i, rows[i].main_ind_addr_c); + polys.main_ind_addr_d.set_if_valid_index(i, rows[i].main_ind_addr_d); + polys.main_internal_return_ptr.set_if_valid_index(i, rows[i].main_internal_return_ptr); + polys.main_inv.set_if_valid_index(i, rows[i].main_inv); + polys.main_kernel_in_offset.set_if_valid_index(i, rows[i].main_kernel_in_offset); + polys.main_kernel_out_offset.set_if_valid_index(i, rows[i].main_kernel_out_offset); + polys.main_l1_to_l2_msg_exists_write_offset.set_if_valid_index(i, + rows[i].main_l1_to_l2_msg_exists_write_offset); + polys.main_l2_gas_remaining.set_if_valid_index(i, rows[i].main_l2_gas_remaining); + polys.main_l2_out_of_gas.set_if_valid_index(i, rows[i].main_l2_out_of_gas); + polys.main_mem_addr_a.set_if_valid_index(i, rows[i].main_mem_addr_a); + polys.main_mem_addr_b.set_if_valid_index(i, rows[i].main_mem_addr_b); + polys.main_mem_addr_c.set_if_valid_index(i, rows[i].main_mem_addr_c); + polys.main_mem_addr_d.set_if_valid_index(i, rows[i].main_mem_addr_d); + polys.main_note_hash_exist_write_offset.set_if_valid_index(i, rows[i].main_note_hash_exist_write_offset); + polys.main_nullifier_exists_write_offset.set_if_valid_index(i, rows[i].main_nullifier_exists_write_offset); + polys.main_nullifier_non_exists_write_offset.set_if_valid_index(i, + rows[i].main_nullifier_non_exists_write_offset); + polys.main_op_err.set_if_valid_index(i, rows[i].main_op_err); + polys.main_opcode_val.set_if_valid_index(i, rows[i].main_opcode_val); + polys.main_pc.set_if_valid_index(i, rows[i].main_pc); + polys.main_r_in_tag.set_if_valid_index(i, rows[i].main_r_in_tag); + polys.main_rwa.set_if_valid_index(i, rows[i].main_rwa); + polys.main_rwb.set_if_valid_index(i, rows[i].main_rwb); + polys.main_rwc.set_if_valid_index(i, rows[i].main_rwc); + polys.main_rwd.set_if_valid_index(i, rows[i].main_rwd); + polys.main_sel_alu.set_if_valid_index(i, rows[i].main_sel_alu); + polys.main_sel_bin.set_if_valid_index(i, rows[i].main_sel_bin); + polys.main_sel_calldata.set_if_valid_index(i, rows[i].main_sel_calldata); + polys.main_sel_execution_row.set_if_valid_index(i, rows[i].main_sel_execution_row); + polys.main_sel_kernel_inputs.set_if_valid_index(i, rows[i].main_sel_kernel_inputs); + polys.main_sel_kernel_out.set_if_valid_index(i, rows[i].main_sel_kernel_out); + polys.main_sel_last.set_if_valid_index(i, rows[i].main_sel_last); + polys.main_sel_mem_op_a.set_if_valid_index(i, rows[i].main_sel_mem_op_a); + polys.main_sel_mem_op_b.set_if_valid_index(i, rows[i].main_sel_mem_op_b); + polys.main_sel_mem_op_c.set_if_valid_index(i, rows[i].main_sel_mem_op_c); + polys.main_sel_mem_op_d.set_if_valid_index(i, rows[i].main_sel_mem_op_d); + polys.main_sel_mov_ia_to_ic.set_if_valid_index(i, rows[i].main_sel_mov_ia_to_ic); + polys.main_sel_mov_ib_to_ic.set_if_valid_index(i, rows[i].main_sel_mov_ib_to_ic); + polys.main_sel_op_add.set_if_valid_index(i, rows[i].main_sel_op_add); + polys.main_sel_op_address.set_if_valid_index(i, rows[i].main_sel_op_address); + polys.main_sel_op_and.set_if_valid_index(i, rows[i].main_sel_op_and); + polys.main_sel_op_block_number.set_if_valid_index(i, rows[i].main_sel_op_block_number); + polys.main_sel_op_calldata_copy.set_if_valid_index(i, rows[i].main_sel_op_calldata_copy); + polys.main_sel_op_cast.set_if_valid_index(i, rows[i].main_sel_op_cast); + polys.main_sel_op_chain_id.set_if_valid_index(i, rows[i].main_sel_op_chain_id); + polys.main_sel_op_cmov.set_if_valid_index(i, rows[i].main_sel_op_cmov); + polys.main_sel_op_dagasleft.set_if_valid_index(i, rows[i].main_sel_op_dagasleft); + polys.main_sel_op_div.set_if_valid_index(i, rows[i].main_sel_op_div); + polys.main_sel_op_ecadd.set_if_valid_index(i, rows[i].main_sel_op_ecadd); + polys.main_sel_op_emit_l2_to_l1_msg.set_if_valid_index(i, rows[i].main_sel_op_emit_l2_to_l1_msg); + polys.main_sel_op_emit_note_hash.set_if_valid_index(i, rows[i].main_sel_op_emit_note_hash); + polys.main_sel_op_emit_nullifier.set_if_valid_index(i, rows[i].main_sel_op_emit_nullifier); + polys.main_sel_op_emit_unencrypted_log.set_if_valid_index(i, rows[i].main_sel_op_emit_unencrypted_log); + polys.main_sel_op_eq.set_if_valid_index(i, rows[i].main_sel_op_eq); + polys.main_sel_op_external_call.set_if_valid_index(i, rows[i].main_sel_op_external_call); + polys.main_sel_op_external_return.set_if_valid_index(i, rows[i].main_sel_op_external_return); + polys.main_sel_op_external_revert.set_if_valid_index(i, rows[i].main_sel_op_external_revert); + polys.main_sel_op_fdiv.set_if_valid_index(i, rows[i].main_sel_op_fdiv); + polys.main_sel_op_fee_per_da_gas.set_if_valid_index(i, rows[i].main_sel_op_fee_per_da_gas); + polys.main_sel_op_fee_per_l2_gas.set_if_valid_index(i, rows[i].main_sel_op_fee_per_l2_gas); + polys.main_sel_op_function_selector.set_if_valid_index(i, rows[i].main_sel_op_function_selector); + polys.main_sel_op_get_contract_instance.set_if_valid_index(i, rows[i].main_sel_op_get_contract_instance); + polys.main_sel_op_internal_call.set_if_valid_index(i, rows[i].main_sel_op_internal_call); + polys.main_sel_op_internal_return.set_if_valid_index(i, rows[i].main_sel_op_internal_return); + polys.main_sel_op_jump.set_if_valid_index(i, rows[i].main_sel_op_jump); + polys.main_sel_op_jumpi.set_if_valid_index(i, rows[i].main_sel_op_jumpi); + polys.main_sel_op_keccak.set_if_valid_index(i, rows[i].main_sel_op_keccak); + polys.main_sel_op_l1_to_l2_msg_exists.set_if_valid_index(i, rows[i].main_sel_op_l1_to_l2_msg_exists); + polys.main_sel_op_l2gasleft.set_if_valid_index(i, rows[i].main_sel_op_l2gasleft); + polys.main_sel_op_lt.set_if_valid_index(i, rows[i].main_sel_op_lt); + polys.main_sel_op_lte.set_if_valid_index(i, rows[i].main_sel_op_lte); + polys.main_sel_op_mov.set_if_valid_index(i, rows[i].main_sel_op_mov); + polys.main_sel_op_msm.set_if_valid_index(i, rows[i].main_sel_op_msm); + polys.main_sel_op_mul.set_if_valid_index(i, rows[i].main_sel_op_mul); + polys.main_sel_op_not.set_if_valid_index(i, rows[i].main_sel_op_not); + polys.main_sel_op_note_hash_exists.set_if_valid_index(i, rows[i].main_sel_op_note_hash_exists); + polys.main_sel_op_nullifier_exists.set_if_valid_index(i, rows[i].main_sel_op_nullifier_exists); + polys.main_sel_op_or.set_if_valid_index(i, rows[i].main_sel_op_or); + polys.main_sel_op_pedersen.set_if_valid_index(i, rows[i].main_sel_op_pedersen); + polys.main_sel_op_pedersen_commit.set_if_valid_index(i, rows[i].main_sel_op_pedersen_commit); + polys.main_sel_op_poseidon2.set_if_valid_index(i, rows[i].main_sel_op_poseidon2); + polys.main_sel_op_radix_le.set_if_valid_index(i, rows[i].main_sel_op_radix_le); + polys.main_sel_op_sender.set_if_valid_index(i, rows[i].main_sel_op_sender); + polys.main_sel_op_set.set_if_valid_index(i, rows[i].main_sel_op_set); + polys.main_sel_op_sha256.set_if_valid_index(i, rows[i].main_sel_op_sha256); + polys.main_sel_op_shl.set_if_valid_index(i, rows[i].main_sel_op_shl); + polys.main_sel_op_shr.set_if_valid_index(i, rows[i].main_sel_op_shr); + polys.main_sel_op_sload.set_if_valid_index(i, rows[i].main_sel_op_sload); + polys.main_sel_op_sstore.set_if_valid_index(i, rows[i].main_sel_op_sstore); + polys.main_sel_op_storage_address.set_if_valid_index(i, rows[i].main_sel_op_storage_address); + polys.main_sel_op_sub.set_if_valid_index(i, rows[i].main_sel_op_sub); + polys.main_sel_op_timestamp.set_if_valid_index(i, rows[i].main_sel_op_timestamp); + polys.main_sel_op_transaction_fee.set_if_valid_index(i, rows[i].main_sel_op_transaction_fee); + polys.main_sel_op_version.set_if_valid_index(i, rows[i].main_sel_op_version); + polys.main_sel_op_xor.set_if_valid_index(i, rows[i].main_sel_op_xor); + polys.main_sel_q_kernel_lookup.set_if_valid_index(i, rows[i].main_sel_q_kernel_lookup); + polys.main_sel_q_kernel_output_lookup.set_if_valid_index(i, rows[i].main_sel_q_kernel_output_lookup); + polys.main_sel_resolve_ind_addr_a.set_if_valid_index(i, rows[i].main_sel_resolve_ind_addr_a); + polys.main_sel_resolve_ind_addr_b.set_if_valid_index(i, rows[i].main_sel_resolve_ind_addr_b); + polys.main_sel_resolve_ind_addr_c.set_if_valid_index(i, rows[i].main_sel_resolve_ind_addr_c); + polys.main_sel_resolve_ind_addr_d.set_if_valid_index(i, rows[i].main_sel_resolve_ind_addr_d); + polys.main_sel_returndata.set_if_valid_index(i, rows[i].main_sel_returndata); + polys.main_sel_rng_16.set_if_valid_index(i, rows[i].main_sel_rng_16); + polys.main_sel_rng_8.set_if_valid_index(i, rows[i].main_sel_rng_8); + polys.main_sel_slice_gadget.set_if_valid_index(i, rows[i].main_sel_slice_gadget); + polys.main_side_effect_counter.set_if_valid_index(i, rows[i].main_side_effect_counter); + polys.main_sload_write_offset.set_if_valid_index(i, rows[i].main_sload_write_offset); + polys.main_space_id.set_if_valid_index(i, rows[i].main_space_id); + polys.main_sstore_write_offset.set_if_valid_index(i, rows[i].main_sstore_write_offset); + polys.main_tag_err.set_if_valid_index(i, rows[i].main_tag_err); + polys.main_w_in_tag.set_if_valid_index(i, rows[i].main_w_in_tag); + polys.mem_addr.set_if_valid_index(i, rows[i].mem_addr); + polys.mem_clk.set_if_valid_index(i, rows[i].mem_clk); + polys.mem_diff.set_if_valid_index(i, rows[i].mem_diff); + polys.mem_glob_addr.set_if_valid_index(i, rows[i].mem_glob_addr); + polys.mem_last.set_if_valid_index(i, rows[i].mem_last); + polys.mem_lastAccess.set_if_valid_index(i, rows[i].mem_lastAccess); + polys.mem_one_min_inv.set_if_valid_index(i, rows[i].mem_one_min_inv); + polys.mem_r_in_tag.set_if_valid_index(i, rows[i].mem_r_in_tag); + polys.mem_rw.set_if_valid_index(i, rows[i].mem_rw); + polys.mem_sel_mem.set_if_valid_index(i, rows[i].mem_sel_mem); + polys.mem_sel_mov_ia_to_ic.set_if_valid_index(i, rows[i].mem_sel_mov_ia_to_ic); + polys.mem_sel_mov_ib_to_ic.set_if_valid_index(i, rows[i].mem_sel_mov_ib_to_ic); + polys.mem_sel_op_a.set_if_valid_index(i, rows[i].mem_sel_op_a); + polys.mem_sel_op_b.set_if_valid_index(i, rows[i].mem_sel_op_b); + polys.mem_sel_op_c.set_if_valid_index(i, rows[i].mem_sel_op_c); + polys.mem_sel_op_cmov.set_if_valid_index(i, rows[i].mem_sel_op_cmov); + polys.mem_sel_op_d.set_if_valid_index(i, rows[i].mem_sel_op_d); + polys.mem_sel_op_poseidon_read_a.set_if_valid_index(i, rows[i].mem_sel_op_poseidon_read_a); + polys.mem_sel_op_poseidon_read_b.set_if_valid_index(i, rows[i].mem_sel_op_poseidon_read_b); + polys.mem_sel_op_poseidon_read_c.set_if_valid_index(i, rows[i].mem_sel_op_poseidon_read_c); + polys.mem_sel_op_poseidon_read_d.set_if_valid_index(i, rows[i].mem_sel_op_poseidon_read_d); + polys.mem_sel_op_poseidon_write_a.set_if_valid_index(i, rows[i].mem_sel_op_poseidon_write_a); + polys.mem_sel_op_poseidon_write_b.set_if_valid_index(i, rows[i].mem_sel_op_poseidon_write_b); + polys.mem_sel_op_poseidon_write_c.set_if_valid_index(i, rows[i].mem_sel_op_poseidon_write_c); + polys.mem_sel_op_poseidon_write_d.set_if_valid_index(i, rows[i].mem_sel_op_poseidon_write_d); + polys.mem_sel_op_slice.set_if_valid_index(i, rows[i].mem_sel_op_slice); + polys.mem_sel_resolve_ind_addr_a.set_if_valid_index(i, rows[i].mem_sel_resolve_ind_addr_a); + polys.mem_sel_resolve_ind_addr_b.set_if_valid_index(i, rows[i].mem_sel_resolve_ind_addr_b); + polys.mem_sel_resolve_ind_addr_c.set_if_valid_index(i, rows[i].mem_sel_resolve_ind_addr_c); + polys.mem_sel_resolve_ind_addr_d.set_if_valid_index(i, rows[i].mem_sel_resolve_ind_addr_d); + polys.mem_sel_rng_chk.set_if_valid_index(i, rows[i].mem_sel_rng_chk); + polys.mem_skip_check_tag.set_if_valid_index(i, rows[i].mem_skip_check_tag); + polys.mem_space_id.set_if_valid_index(i, rows[i].mem_space_id); + polys.mem_tag.set_if_valid_index(i, rows[i].mem_tag); + polys.mem_tag_err.set_if_valid_index(i, rows[i].mem_tag_err); + polys.mem_tsp.set_if_valid_index(i, rows[i].mem_tsp); + polys.mem_val.set_if_valid_index(i, rows[i].mem_val); + polys.mem_w_in_tag.set_if_valid_index(i, rows[i].mem_w_in_tag); + polys.pedersen_clk.set_if_valid_index(i, rows[i].pedersen_clk); + polys.pedersen_input.set_if_valid_index(i, rows[i].pedersen_input); + polys.pedersen_output.set_if_valid_index(i, rows[i].pedersen_output); + polys.pedersen_sel_pedersen.set_if_valid_index(i, rows[i].pedersen_sel_pedersen); + polys.poseidon2_B_10_0.set_if_valid_index(i, rows[i].poseidon2_B_10_0); + polys.poseidon2_B_10_1.set_if_valid_index(i, rows[i].poseidon2_B_10_1); + polys.poseidon2_B_10_2.set_if_valid_index(i, rows[i].poseidon2_B_10_2); + polys.poseidon2_B_10_3.set_if_valid_index(i, rows[i].poseidon2_B_10_3); + polys.poseidon2_B_11_0.set_if_valid_index(i, rows[i].poseidon2_B_11_0); + polys.poseidon2_B_11_1.set_if_valid_index(i, rows[i].poseidon2_B_11_1); + polys.poseidon2_B_11_2.set_if_valid_index(i, rows[i].poseidon2_B_11_2); + polys.poseidon2_B_11_3.set_if_valid_index(i, rows[i].poseidon2_B_11_3); + polys.poseidon2_B_12_0.set_if_valid_index(i, rows[i].poseidon2_B_12_0); + polys.poseidon2_B_12_1.set_if_valid_index(i, rows[i].poseidon2_B_12_1); + polys.poseidon2_B_12_2.set_if_valid_index(i, rows[i].poseidon2_B_12_2); + polys.poseidon2_B_12_3.set_if_valid_index(i, rows[i].poseidon2_B_12_3); + polys.poseidon2_B_13_0.set_if_valid_index(i, rows[i].poseidon2_B_13_0); + polys.poseidon2_B_13_1.set_if_valid_index(i, rows[i].poseidon2_B_13_1); + polys.poseidon2_B_13_2.set_if_valid_index(i, rows[i].poseidon2_B_13_2); + polys.poseidon2_B_13_3.set_if_valid_index(i, rows[i].poseidon2_B_13_3); + polys.poseidon2_B_14_0.set_if_valid_index(i, rows[i].poseidon2_B_14_0); + polys.poseidon2_B_14_1.set_if_valid_index(i, rows[i].poseidon2_B_14_1); + polys.poseidon2_B_14_2.set_if_valid_index(i, rows[i].poseidon2_B_14_2); + polys.poseidon2_B_14_3.set_if_valid_index(i, rows[i].poseidon2_B_14_3); + polys.poseidon2_B_15_0.set_if_valid_index(i, rows[i].poseidon2_B_15_0); + polys.poseidon2_B_15_1.set_if_valid_index(i, rows[i].poseidon2_B_15_1); + polys.poseidon2_B_15_2.set_if_valid_index(i, rows[i].poseidon2_B_15_2); + polys.poseidon2_B_15_3.set_if_valid_index(i, rows[i].poseidon2_B_15_3); + polys.poseidon2_B_16_0.set_if_valid_index(i, rows[i].poseidon2_B_16_0); + polys.poseidon2_B_16_1.set_if_valid_index(i, rows[i].poseidon2_B_16_1); + polys.poseidon2_B_16_2.set_if_valid_index(i, rows[i].poseidon2_B_16_2); + polys.poseidon2_B_16_3.set_if_valid_index(i, rows[i].poseidon2_B_16_3); + polys.poseidon2_B_17_0.set_if_valid_index(i, rows[i].poseidon2_B_17_0); + polys.poseidon2_B_17_1.set_if_valid_index(i, rows[i].poseidon2_B_17_1); + polys.poseidon2_B_17_2.set_if_valid_index(i, rows[i].poseidon2_B_17_2); + polys.poseidon2_B_17_3.set_if_valid_index(i, rows[i].poseidon2_B_17_3); + polys.poseidon2_B_18_0.set_if_valid_index(i, rows[i].poseidon2_B_18_0); + polys.poseidon2_B_18_1.set_if_valid_index(i, rows[i].poseidon2_B_18_1); + polys.poseidon2_B_18_2.set_if_valid_index(i, rows[i].poseidon2_B_18_2); + polys.poseidon2_B_18_3.set_if_valid_index(i, rows[i].poseidon2_B_18_3); + polys.poseidon2_B_19_0.set_if_valid_index(i, rows[i].poseidon2_B_19_0); + polys.poseidon2_B_19_1.set_if_valid_index(i, rows[i].poseidon2_B_19_1); + polys.poseidon2_B_19_2.set_if_valid_index(i, rows[i].poseidon2_B_19_2); + polys.poseidon2_B_19_3.set_if_valid_index(i, rows[i].poseidon2_B_19_3); + polys.poseidon2_B_20_0.set_if_valid_index(i, rows[i].poseidon2_B_20_0); + polys.poseidon2_B_20_1.set_if_valid_index(i, rows[i].poseidon2_B_20_1); + polys.poseidon2_B_20_2.set_if_valid_index(i, rows[i].poseidon2_B_20_2); + polys.poseidon2_B_20_3.set_if_valid_index(i, rows[i].poseidon2_B_20_3); + polys.poseidon2_B_21_0.set_if_valid_index(i, rows[i].poseidon2_B_21_0); + polys.poseidon2_B_21_1.set_if_valid_index(i, rows[i].poseidon2_B_21_1); + polys.poseidon2_B_21_2.set_if_valid_index(i, rows[i].poseidon2_B_21_2); + polys.poseidon2_B_21_3.set_if_valid_index(i, rows[i].poseidon2_B_21_3); + polys.poseidon2_B_22_0.set_if_valid_index(i, rows[i].poseidon2_B_22_0); + polys.poseidon2_B_22_1.set_if_valid_index(i, rows[i].poseidon2_B_22_1); + polys.poseidon2_B_22_2.set_if_valid_index(i, rows[i].poseidon2_B_22_2); + polys.poseidon2_B_22_3.set_if_valid_index(i, rows[i].poseidon2_B_22_3); + polys.poseidon2_B_23_0.set_if_valid_index(i, rows[i].poseidon2_B_23_0); + polys.poseidon2_B_23_1.set_if_valid_index(i, rows[i].poseidon2_B_23_1); + polys.poseidon2_B_23_2.set_if_valid_index(i, rows[i].poseidon2_B_23_2); + polys.poseidon2_B_23_3.set_if_valid_index(i, rows[i].poseidon2_B_23_3); + polys.poseidon2_B_24_0.set_if_valid_index(i, rows[i].poseidon2_B_24_0); + polys.poseidon2_B_24_1.set_if_valid_index(i, rows[i].poseidon2_B_24_1); + polys.poseidon2_B_24_2.set_if_valid_index(i, rows[i].poseidon2_B_24_2); + polys.poseidon2_B_24_3.set_if_valid_index(i, rows[i].poseidon2_B_24_3); + polys.poseidon2_B_25_0.set_if_valid_index(i, rows[i].poseidon2_B_25_0); + polys.poseidon2_B_25_1.set_if_valid_index(i, rows[i].poseidon2_B_25_1); + polys.poseidon2_B_25_2.set_if_valid_index(i, rows[i].poseidon2_B_25_2); + polys.poseidon2_B_25_3.set_if_valid_index(i, rows[i].poseidon2_B_25_3); + polys.poseidon2_B_26_0.set_if_valid_index(i, rows[i].poseidon2_B_26_0); + polys.poseidon2_B_26_1.set_if_valid_index(i, rows[i].poseidon2_B_26_1); + polys.poseidon2_B_26_2.set_if_valid_index(i, rows[i].poseidon2_B_26_2); + polys.poseidon2_B_26_3.set_if_valid_index(i, rows[i].poseidon2_B_26_3); + polys.poseidon2_B_27_0.set_if_valid_index(i, rows[i].poseidon2_B_27_0); + polys.poseidon2_B_27_1.set_if_valid_index(i, rows[i].poseidon2_B_27_1); + polys.poseidon2_B_27_2.set_if_valid_index(i, rows[i].poseidon2_B_27_2); + polys.poseidon2_B_27_3.set_if_valid_index(i, rows[i].poseidon2_B_27_3); + polys.poseidon2_B_28_0.set_if_valid_index(i, rows[i].poseidon2_B_28_0); + polys.poseidon2_B_28_1.set_if_valid_index(i, rows[i].poseidon2_B_28_1); + polys.poseidon2_B_28_2.set_if_valid_index(i, rows[i].poseidon2_B_28_2); + polys.poseidon2_B_28_3.set_if_valid_index(i, rows[i].poseidon2_B_28_3); + polys.poseidon2_B_29_0.set_if_valid_index(i, rows[i].poseidon2_B_29_0); + polys.poseidon2_B_29_1.set_if_valid_index(i, rows[i].poseidon2_B_29_1); + polys.poseidon2_B_29_2.set_if_valid_index(i, rows[i].poseidon2_B_29_2); + polys.poseidon2_B_29_3.set_if_valid_index(i, rows[i].poseidon2_B_29_3); + polys.poseidon2_B_30_0.set_if_valid_index(i, rows[i].poseidon2_B_30_0); + polys.poseidon2_B_30_1.set_if_valid_index(i, rows[i].poseidon2_B_30_1); + polys.poseidon2_B_30_2.set_if_valid_index(i, rows[i].poseidon2_B_30_2); + polys.poseidon2_B_30_3.set_if_valid_index(i, rows[i].poseidon2_B_30_3); + polys.poseidon2_B_31_0.set_if_valid_index(i, rows[i].poseidon2_B_31_0); + polys.poseidon2_B_31_1.set_if_valid_index(i, rows[i].poseidon2_B_31_1); + polys.poseidon2_B_31_2.set_if_valid_index(i, rows[i].poseidon2_B_31_2); + polys.poseidon2_B_31_3.set_if_valid_index(i, rows[i].poseidon2_B_31_3); + polys.poseidon2_B_32_0.set_if_valid_index(i, rows[i].poseidon2_B_32_0); + polys.poseidon2_B_32_1.set_if_valid_index(i, rows[i].poseidon2_B_32_1); + polys.poseidon2_B_32_2.set_if_valid_index(i, rows[i].poseidon2_B_32_2); + polys.poseidon2_B_32_3.set_if_valid_index(i, rows[i].poseidon2_B_32_3); + polys.poseidon2_B_33_0.set_if_valid_index(i, rows[i].poseidon2_B_33_0); + polys.poseidon2_B_33_1.set_if_valid_index(i, rows[i].poseidon2_B_33_1); + polys.poseidon2_B_33_2.set_if_valid_index(i, rows[i].poseidon2_B_33_2); + polys.poseidon2_B_33_3.set_if_valid_index(i, rows[i].poseidon2_B_33_3); + polys.poseidon2_B_34_0.set_if_valid_index(i, rows[i].poseidon2_B_34_0); + polys.poseidon2_B_34_1.set_if_valid_index(i, rows[i].poseidon2_B_34_1); + polys.poseidon2_B_34_2.set_if_valid_index(i, rows[i].poseidon2_B_34_2); + polys.poseidon2_B_34_3.set_if_valid_index(i, rows[i].poseidon2_B_34_3); + polys.poseidon2_B_35_0.set_if_valid_index(i, rows[i].poseidon2_B_35_0); + polys.poseidon2_B_35_1.set_if_valid_index(i, rows[i].poseidon2_B_35_1); + polys.poseidon2_B_35_2.set_if_valid_index(i, rows[i].poseidon2_B_35_2); + polys.poseidon2_B_35_3.set_if_valid_index(i, rows[i].poseidon2_B_35_3); + polys.poseidon2_B_36_0.set_if_valid_index(i, rows[i].poseidon2_B_36_0); + polys.poseidon2_B_36_1.set_if_valid_index(i, rows[i].poseidon2_B_36_1); + polys.poseidon2_B_36_2.set_if_valid_index(i, rows[i].poseidon2_B_36_2); + polys.poseidon2_B_36_3.set_if_valid_index(i, rows[i].poseidon2_B_36_3); + polys.poseidon2_B_37_0.set_if_valid_index(i, rows[i].poseidon2_B_37_0); + polys.poseidon2_B_37_1.set_if_valid_index(i, rows[i].poseidon2_B_37_1); + polys.poseidon2_B_37_2.set_if_valid_index(i, rows[i].poseidon2_B_37_2); + polys.poseidon2_B_37_3.set_if_valid_index(i, rows[i].poseidon2_B_37_3); + polys.poseidon2_B_38_0.set_if_valid_index(i, rows[i].poseidon2_B_38_0); + polys.poseidon2_B_38_1.set_if_valid_index(i, rows[i].poseidon2_B_38_1); + polys.poseidon2_B_38_2.set_if_valid_index(i, rows[i].poseidon2_B_38_2); + polys.poseidon2_B_38_3.set_if_valid_index(i, rows[i].poseidon2_B_38_3); + polys.poseidon2_B_39_0.set_if_valid_index(i, rows[i].poseidon2_B_39_0); + polys.poseidon2_B_39_1.set_if_valid_index(i, rows[i].poseidon2_B_39_1); + polys.poseidon2_B_39_2.set_if_valid_index(i, rows[i].poseidon2_B_39_2); + polys.poseidon2_B_39_3.set_if_valid_index(i, rows[i].poseidon2_B_39_3); + polys.poseidon2_B_40_0.set_if_valid_index(i, rows[i].poseidon2_B_40_0); + polys.poseidon2_B_40_1.set_if_valid_index(i, rows[i].poseidon2_B_40_1); + polys.poseidon2_B_40_2.set_if_valid_index(i, rows[i].poseidon2_B_40_2); + polys.poseidon2_B_40_3.set_if_valid_index(i, rows[i].poseidon2_B_40_3); + polys.poseidon2_B_41_0.set_if_valid_index(i, rows[i].poseidon2_B_41_0); + polys.poseidon2_B_41_1.set_if_valid_index(i, rows[i].poseidon2_B_41_1); + polys.poseidon2_B_41_2.set_if_valid_index(i, rows[i].poseidon2_B_41_2); + polys.poseidon2_B_41_3.set_if_valid_index(i, rows[i].poseidon2_B_41_3); + polys.poseidon2_B_42_0.set_if_valid_index(i, rows[i].poseidon2_B_42_0); + polys.poseidon2_B_42_1.set_if_valid_index(i, rows[i].poseidon2_B_42_1); + polys.poseidon2_B_42_2.set_if_valid_index(i, rows[i].poseidon2_B_42_2); + polys.poseidon2_B_42_3.set_if_valid_index(i, rows[i].poseidon2_B_42_3); + polys.poseidon2_B_43_0.set_if_valid_index(i, rows[i].poseidon2_B_43_0); + polys.poseidon2_B_43_1.set_if_valid_index(i, rows[i].poseidon2_B_43_1); + polys.poseidon2_B_43_2.set_if_valid_index(i, rows[i].poseidon2_B_43_2); + polys.poseidon2_B_43_3.set_if_valid_index(i, rows[i].poseidon2_B_43_3); + polys.poseidon2_B_44_0.set_if_valid_index(i, rows[i].poseidon2_B_44_0); + polys.poseidon2_B_44_1.set_if_valid_index(i, rows[i].poseidon2_B_44_1); + polys.poseidon2_B_44_2.set_if_valid_index(i, rows[i].poseidon2_B_44_2); + polys.poseidon2_B_44_3.set_if_valid_index(i, rows[i].poseidon2_B_44_3); + polys.poseidon2_B_45_0.set_if_valid_index(i, rows[i].poseidon2_B_45_0); + polys.poseidon2_B_45_1.set_if_valid_index(i, rows[i].poseidon2_B_45_1); + polys.poseidon2_B_45_2.set_if_valid_index(i, rows[i].poseidon2_B_45_2); + polys.poseidon2_B_45_3.set_if_valid_index(i, rows[i].poseidon2_B_45_3); + polys.poseidon2_B_46_0.set_if_valid_index(i, rows[i].poseidon2_B_46_0); + polys.poseidon2_B_46_1.set_if_valid_index(i, rows[i].poseidon2_B_46_1); + polys.poseidon2_B_46_2.set_if_valid_index(i, rows[i].poseidon2_B_46_2); + polys.poseidon2_B_46_3.set_if_valid_index(i, rows[i].poseidon2_B_46_3); + polys.poseidon2_B_47_0.set_if_valid_index(i, rows[i].poseidon2_B_47_0); + polys.poseidon2_B_47_1.set_if_valid_index(i, rows[i].poseidon2_B_47_1); + polys.poseidon2_B_47_2.set_if_valid_index(i, rows[i].poseidon2_B_47_2); + polys.poseidon2_B_47_3.set_if_valid_index(i, rows[i].poseidon2_B_47_3); + polys.poseidon2_B_48_0.set_if_valid_index(i, rows[i].poseidon2_B_48_0); + polys.poseidon2_B_48_1.set_if_valid_index(i, rows[i].poseidon2_B_48_1); + polys.poseidon2_B_48_2.set_if_valid_index(i, rows[i].poseidon2_B_48_2); + polys.poseidon2_B_48_3.set_if_valid_index(i, rows[i].poseidon2_B_48_3); + polys.poseidon2_B_49_0.set_if_valid_index(i, rows[i].poseidon2_B_49_0); + polys.poseidon2_B_49_1.set_if_valid_index(i, rows[i].poseidon2_B_49_1); + polys.poseidon2_B_49_2.set_if_valid_index(i, rows[i].poseidon2_B_49_2); + polys.poseidon2_B_49_3.set_if_valid_index(i, rows[i].poseidon2_B_49_3); + polys.poseidon2_B_4_0.set_if_valid_index(i, rows[i].poseidon2_B_4_0); + polys.poseidon2_B_4_1.set_if_valid_index(i, rows[i].poseidon2_B_4_1); + polys.poseidon2_B_4_2.set_if_valid_index(i, rows[i].poseidon2_B_4_2); + polys.poseidon2_B_4_3.set_if_valid_index(i, rows[i].poseidon2_B_4_3); + polys.poseidon2_B_50_0.set_if_valid_index(i, rows[i].poseidon2_B_50_0); + polys.poseidon2_B_50_1.set_if_valid_index(i, rows[i].poseidon2_B_50_1); + polys.poseidon2_B_50_2.set_if_valid_index(i, rows[i].poseidon2_B_50_2); + polys.poseidon2_B_50_3.set_if_valid_index(i, rows[i].poseidon2_B_50_3); + polys.poseidon2_B_51_0.set_if_valid_index(i, rows[i].poseidon2_B_51_0); + polys.poseidon2_B_51_1.set_if_valid_index(i, rows[i].poseidon2_B_51_1); + polys.poseidon2_B_51_2.set_if_valid_index(i, rows[i].poseidon2_B_51_2); + polys.poseidon2_B_51_3.set_if_valid_index(i, rows[i].poseidon2_B_51_3); + polys.poseidon2_B_52_0.set_if_valid_index(i, rows[i].poseidon2_B_52_0); + polys.poseidon2_B_52_1.set_if_valid_index(i, rows[i].poseidon2_B_52_1); + polys.poseidon2_B_52_2.set_if_valid_index(i, rows[i].poseidon2_B_52_2); + polys.poseidon2_B_52_3.set_if_valid_index(i, rows[i].poseidon2_B_52_3); + polys.poseidon2_B_53_0.set_if_valid_index(i, rows[i].poseidon2_B_53_0); + polys.poseidon2_B_53_1.set_if_valid_index(i, rows[i].poseidon2_B_53_1); + polys.poseidon2_B_53_2.set_if_valid_index(i, rows[i].poseidon2_B_53_2); + polys.poseidon2_B_53_3.set_if_valid_index(i, rows[i].poseidon2_B_53_3); + polys.poseidon2_B_54_0.set_if_valid_index(i, rows[i].poseidon2_B_54_0); + polys.poseidon2_B_54_1.set_if_valid_index(i, rows[i].poseidon2_B_54_1); + polys.poseidon2_B_54_2.set_if_valid_index(i, rows[i].poseidon2_B_54_2); + polys.poseidon2_B_54_3.set_if_valid_index(i, rows[i].poseidon2_B_54_3); + polys.poseidon2_B_55_0.set_if_valid_index(i, rows[i].poseidon2_B_55_0); + polys.poseidon2_B_55_1.set_if_valid_index(i, rows[i].poseidon2_B_55_1); + polys.poseidon2_B_55_2.set_if_valid_index(i, rows[i].poseidon2_B_55_2); + polys.poseidon2_B_55_3.set_if_valid_index(i, rows[i].poseidon2_B_55_3); + polys.poseidon2_B_56_0.set_if_valid_index(i, rows[i].poseidon2_B_56_0); + polys.poseidon2_B_56_1.set_if_valid_index(i, rows[i].poseidon2_B_56_1); + polys.poseidon2_B_56_2.set_if_valid_index(i, rows[i].poseidon2_B_56_2); + polys.poseidon2_B_56_3.set_if_valid_index(i, rows[i].poseidon2_B_56_3); + polys.poseidon2_B_57_0.set_if_valid_index(i, rows[i].poseidon2_B_57_0); + polys.poseidon2_B_57_1.set_if_valid_index(i, rows[i].poseidon2_B_57_1); + polys.poseidon2_B_57_2.set_if_valid_index(i, rows[i].poseidon2_B_57_2); + polys.poseidon2_B_57_3.set_if_valid_index(i, rows[i].poseidon2_B_57_3); + polys.poseidon2_B_58_0.set_if_valid_index(i, rows[i].poseidon2_B_58_0); + polys.poseidon2_B_58_1.set_if_valid_index(i, rows[i].poseidon2_B_58_1); + polys.poseidon2_B_58_2.set_if_valid_index(i, rows[i].poseidon2_B_58_2); + polys.poseidon2_B_58_3.set_if_valid_index(i, rows[i].poseidon2_B_58_3); + polys.poseidon2_B_59_0.set_if_valid_index(i, rows[i].poseidon2_B_59_0); + polys.poseidon2_B_59_1.set_if_valid_index(i, rows[i].poseidon2_B_59_1); + polys.poseidon2_B_59_2.set_if_valid_index(i, rows[i].poseidon2_B_59_2); + polys.poseidon2_B_59_3.set_if_valid_index(i, rows[i].poseidon2_B_59_3); + polys.poseidon2_B_5_0.set_if_valid_index(i, rows[i].poseidon2_B_5_0); + polys.poseidon2_B_5_1.set_if_valid_index(i, rows[i].poseidon2_B_5_1); + polys.poseidon2_B_5_2.set_if_valid_index(i, rows[i].poseidon2_B_5_2); + polys.poseidon2_B_5_3.set_if_valid_index(i, rows[i].poseidon2_B_5_3); + polys.poseidon2_B_6_0.set_if_valid_index(i, rows[i].poseidon2_B_6_0); + polys.poseidon2_B_6_1.set_if_valid_index(i, rows[i].poseidon2_B_6_1); + polys.poseidon2_B_6_2.set_if_valid_index(i, rows[i].poseidon2_B_6_2); + polys.poseidon2_B_6_3.set_if_valid_index(i, rows[i].poseidon2_B_6_3); + polys.poseidon2_B_7_0.set_if_valid_index(i, rows[i].poseidon2_B_7_0); + polys.poseidon2_B_7_1.set_if_valid_index(i, rows[i].poseidon2_B_7_1); + polys.poseidon2_B_7_2.set_if_valid_index(i, rows[i].poseidon2_B_7_2); + polys.poseidon2_B_7_3.set_if_valid_index(i, rows[i].poseidon2_B_7_3); + polys.poseidon2_B_8_0.set_if_valid_index(i, rows[i].poseidon2_B_8_0); + polys.poseidon2_B_8_1.set_if_valid_index(i, rows[i].poseidon2_B_8_1); + polys.poseidon2_B_8_2.set_if_valid_index(i, rows[i].poseidon2_B_8_2); + polys.poseidon2_B_8_3.set_if_valid_index(i, rows[i].poseidon2_B_8_3); + polys.poseidon2_B_9_0.set_if_valid_index(i, rows[i].poseidon2_B_9_0); + polys.poseidon2_B_9_1.set_if_valid_index(i, rows[i].poseidon2_B_9_1); + polys.poseidon2_B_9_2.set_if_valid_index(i, rows[i].poseidon2_B_9_2); + polys.poseidon2_B_9_3.set_if_valid_index(i, rows[i].poseidon2_B_9_3); + polys.poseidon2_EXT_LAYER_4.set_if_valid_index(i, rows[i].poseidon2_EXT_LAYER_4); + polys.poseidon2_EXT_LAYER_5.set_if_valid_index(i, rows[i].poseidon2_EXT_LAYER_5); + polys.poseidon2_EXT_LAYER_6.set_if_valid_index(i, rows[i].poseidon2_EXT_LAYER_6); + polys.poseidon2_EXT_LAYER_7.set_if_valid_index(i, rows[i].poseidon2_EXT_LAYER_7); + polys.poseidon2_T_0_4.set_if_valid_index(i, rows[i].poseidon2_T_0_4); + polys.poseidon2_T_0_5.set_if_valid_index(i, rows[i].poseidon2_T_0_5); + polys.poseidon2_T_0_6.set_if_valid_index(i, rows[i].poseidon2_T_0_6); + polys.poseidon2_T_0_7.set_if_valid_index(i, rows[i].poseidon2_T_0_7); + polys.poseidon2_T_1_4.set_if_valid_index(i, rows[i].poseidon2_T_1_4); + polys.poseidon2_T_1_5.set_if_valid_index(i, rows[i].poseidon2_T_1_5); + polys.poseidon2_T_1_6.set_if_valid_index(i, rows[i].poseidon2_T_1_6); + polys.poseidon2_T_1_7.set_if_valid_index(i, rows[i].poseidon2_T_1_7); + polys.poseidon2_T_2_4.set_if_valid_index(i, rows[i].poseidon2_T_2_4); + polys.poseidon2_T_2_5.set_if_valid_index(i, rows[i].poseidon2_T_2_5); + polys.poseidon2_T_2_6.set_if_valid_index(i, rows[i].poseidon2_T_2_6); + polys.poseidon2_T_2_7.set_if_valid_index(i, rows[i].poseidon2_T_2_7); + polys.poseidon2_T_3_4.set_if_valid_index(i, rows[i].poseidon2_T_3_4); + polys.poseidon2_T_3_5.set_if_valid_index(i, rows[i].poseidon2_T_3_5); + polys.poseidon2_T_3_6.set_if_valid_index(i, rows[i].poseidon2_T_3_6); + polys.poseidon2_T_3_7.set_if_valid_index(i, rows[i].poseidon2_T_3_7); + polys.poseidon2_T_60_4.set_if_valid_index(i, rows[i].poseidon2_T_60_4); + polys.poseidon2_T_60_5.set_if_valid_index(i, rows[i].poseidon2_T_60_5); + polys.poseidon2_T_60_6.set_if_valid_index(i, rows[i].poseidon2_T_60_6); + polys.poseidon2_T_60_7.set_if_valid_index(i, rows[i].poseidon2_T_60_7); + polys.poseidon2_T_61_4.set_if_valid_index(i, rows[i].poseidon2_T_61_4); + polys.poseidon2_T_61_5.set_if_valid_index(i, rows[i].poseidon2_T_61_5); + polys.poseidon2_T_61_6.set_if_valid_index(i, rows[i].poseidon2_T_61_6); + polys.poseidon2_T_61_7.set_if_valid_index(i, rows[i].poseidon2_T_61_7); + polys.poseidon2_T_62_4.set_if_valid_index(i, rows[i].poseidon2_T_62_4); + polys.poseidon2_T_62_5.set_if_valid_index(i, rows[i].poseidon2_T_62_5); + polys.poseidon2_T_62_6.set_if_valid_index(i, rows[i].poseidon2_T_62_6); + polys.poseidon2_T_62_7.set_if_valid_index(i, rows[i].poseidon2_T_62_7); + polys.poseidon2_T_63_4.set_if_valid_index(i, rows[i].poseidon2_T_63_4); + polys.poseidon2_T_63_5.set_if_valid_index(i, rows[i].poseidon2_T_63_5); + polys.poseidon2_T_63_6.set_if_valid_index(i, rows[i].poseidon2_T_63_6); + polys.poseidon2_T_63_7.set_if_valid_index(i, rows[i].poseidon2_T_63_7); + polys.poseidon2_a_0.set_if_valid_index(i, rows[i].poseidon2_a_0); + polys.poseidon2_a_1.set_if_valid_index(i, rows[i].poseidon2_a_1); + polys.poseidon2_a_2.set_if_valid_index(i, rows[i].poseidon2_a_2); + polys.poseidon2_a_3.set_if_valid_index(i, rows[i].poseidon2_a_3); + polys.poseidon2_b_0.set_if_valid_index(i, rows[i].poseidon2_b_0); + polys.poseidon2_b_1.set_if_valid_index(i, rows[i].poseidon2_b_1); + polys.poseidon2_b_2.set_if_valid_index(i, rows[i].poseidon2_b_2); + polys.poseidon2_b_3.set_if_valid_index(i, rows[i].poseidon2_b_3); + polys.poseidon2_clk.set_if_valid_index(i, rows[i].poseidon2_clk); + polys.poseidon2_input_addr.set_if_valid_index(i, rows[i].poseidon2_input_addr); + polys.poseidon2_mem_addr_read_a.set_if_valid_index(i, rows[i].poseidon2_mem_addr_read_a); + polys.poseidon2_mem_addr_read_b.set_if_valid_index(i, rows[i].poseidon2_mem_addr_read_b); + polys.poseidon2_mem_addr_read_c.set_if_valid_index(i, rows[i].poseidon2_mem_addr_read_c); + polys.poseidon2_mem_addr_read_d.set_if_valid_index(i, rows[i].poseidon2_mem_addr_read_d); + polys.poseidon2_mem_addr_write_a.set_if_valid_index(i, rows[i].poseidon2_mem_addr_write_a); + polys.poseidon2_mem_addr_write_b.set_if_valid_index(i, rows[i].poseidon2_mem_addr_write_b); + polys.poseidon2_mem_addr_write_c.set_if_valid_index(i, rows[i].poseidon2_mem_addr_write_c); + polys.poseidon2_mem_addr_write_d.set_if_valid_index(i, rows[i].poseidon2_mem_addr_write_d); + polys.poseidon2_output_addr.set_if_valid_index(i, rows[i].poseidon2_output_addr); + polys.poseidon2_sel_poseidon_perm.set_if_valid_index(i, rows[i].poseidon2_sel_poseidon_perm); + polys.range_check_alu_rng_chk.set_if_valid_index(i, rows[i].range_check_alu_rng_chk); + polys.range_check_clk.set_if_valid_index(i, rows[i].range_check_clk); + polys.range_check_cmp_hi_bits_rng_chk.set_if_valid_index(i, rows[i].range_check_cmp_hi_bits_rng_chk); + polys.range_check_cmp_lo_bits_rng_chk.set_if_valid_index(i, rows[i].range_check_cmp_lo_bits_rng_chk); + polys.range_check_dyn_diff.set_if_valid_index(i, rows[i].range_check_dyn_diff); + polys.range_check_dyn_rng_chk_bits.set_if_valid_index(i, rows[i].range_check_dyn_rng_chk_bits); + polys.range_check_dyn_rng_chk_pow_2.set_if_valid_index(i, rows[i].range_check_dyn_rng_chk_pow_2); + polys.range_check_gas_da_rng_chk.set_if_valid_index(i, rows[i].range_check_gas_da_rng_chk); + polys.range_check_gas_l2_rng_chk.set_if_valid_index(i, rows[i].range_check_gas_l2_rng_chk); + polys.range_check_is_lte_u112.set_if_valid_index(i, rows[i].range_check_is_lte_u112); + polys.range_check_is_lte_u128.set_if_valid_index(i, rows[i].range_check_is_lte_u128); + polys.range_check_is_lte_u16.set_if_valid_index(i, rows[i].range_check_is_lte_u16); + polys.range_check_is_lte_u32.set_if_valid_index(i, rows[i].range_check_is_lte_u32); + polys.range_check_is_lte_u48.set_if_valid_index(i, rows[i].range_check_is_lte_u48); + polys.range_check_is_lte_u64.set_if_valid_index(i, rows[i].range_check_is_lte_u64); + polys.range_check_is_lte_u80.set_if_valid_index(i, rows[i].range_check_is_lte_u80); + polys.range_check_is_lte_u96.set_if_valid_index(i, rows[i].range_check_is_lte_u96); + polys.range_check_mem_rng_chk.set_if_valid_index(i, rows[i].range_check_mem_rng_chk); + polys.range_check_rng_chk_bits.set_if_valid_index(i, rows[i].range_check_rng_chk_bits); + polys.range_check_sel_lookup_0.set_if_valid_index(i, rows[i].range_check_sel_lookup_0); + polys.range_check_sel_lookup_1.set_if_valid_index(i, rows[i].range_check_sel_lookup_1); + polys.range_check_sel_lookup_2.set_if_valid_index(i, rows[i].range_check_sel_lookup_2); + polys.range_check_sel_lookup_3.set_if_valid_index(i, rows[i].range_check_sel_lookup_3); + polys.range_check_sel_lookup_4.set_if_valid_index(i, rows[i].range_check_sel_lookup_4); + polys.range_check_sel_lookup_5.set_if_valid_index(i, rows[i].range_check_sel_lookup_5); + polys.range_check_sel_lookup_6.set_if_valid_index(i, rows[i].range_check_sel_lookup_6); + polys.range_check_sel_rng_chk.set_if_valid_index(i, rows[i].range_check_sel_rng_chk); + polys.range_check_u16_r0.set_if_valid_index(i, rows[i].range_check_u16_r0); + polys.range_check_u16_r1.set_if_valid_index(i, rows[i].range_check_u16_r1); + polys.range_check_u16_r2.set_if_valid_index(i, rows[i].range_check_u16_r2); + polys.range_check_u16_r3.set_if_valid_index(i, rows[i].range_check_u16_r3); + polys.range_check_u16_r4.set_if_valid_index(i, rows[i].range_check_u16_r4); + polys.range_check_u16_r5.set_if_valid_index(i, rows[i].range_check_u16_r5); + polys.range_check_u16_r6.set_if_valid_index(i, rows[i].range_check_u16_r6); + polys.range_check_u16_r7.set_if_valid_index(i, rows[i].range_check_u16_r7); + polys.range_check_value.set_if_valid_index(i, rows[i].range_check_value); + polys.sha256_clk.set_if_valid_index(i, rows[i].sha256_clk); + polys.sha256_input.set_if_valid_index(i, rows[i].sha256_input); + polys.sha256_output.set_if_valid_index(i, rows[i].sha256_output); + polys.sha256_sel_sha256_compression.set_if_valid_index(i, rows[i].sha256_sel_sha256_compression); + polys.sha256_state.set_if_valid_index(i, rows[i].sha256_state); + polys.slice_addr.set_if_valid_index(i, rows[i].slice_addr); + polys.slice_clk.set_if_valid_index(i, rows[i].slice_clk); + polys.slice_cnt.set_if_valid_index(i, rows[i].slice_cnt); + polys.slice_col_offset.set_if_valid_index(i, rows[i].slice_col_offset); + polys.slice_one_min_inv.set_if_valid_index(i, rows[i].slice_one_min_inv); + polys.slice_sel_cd_cpy.set_if_valid_index(i, rows[i].slice_sel_cd_cpy); + polys.slice_sel_mem_active.set_if_valid_index(i, rows[i].slice_sel_mem_active); + polys.slice_sel_return.set_if_valid_index(i, rows[i].slice_sel_return); + polys.slice_sel_start.set_if_valid_index(i, rows[i].slice_sel_start); + polys.slice_space_id.set_if_valid_index(i, rows[i].slice_space_id); + polys.slice_val.set_if_valid_index(i, rows[i].slice_val); + polys.lookup_rng_chk_pow_2_counts.set_if_valid_index(i, rows[i].lookup_rng_chk_pow_2_counts); + polys.lookup_rng_chk_diff_counts.set_if_valid_index(i, rows[i].lookup_rng_chk_diff_counts); + polys.lookup_rng_chk_0_counts.set_if_valid_index(i, rows[i].lookup_rng_chk_0_counts); + polys.lookup_rng_chk_1_counts.set_if_valid_index(i, rows[i].lookup_rng_chk_1_counts); + polys.lookup_rng_chk_2_counts.set_if_valid_index(i, rows[i].lookup_rng_chk_2_counts); + polys.lookup_rng_chk_3_counts.set_if_valid_index(i, rows[i].lookup_rng_chk_3_counts); + polys.lookup_rng_chk_4_counts.set_if_valid_index(i, rows[i].lookup_rng_chk_4_counts); + polys.lookup_rng_chk_5_counts.set_if_valid_index(i, rows[i].lookup_rng_chk_5_counts); + polys.lookup_rng_chk_6_counts.set_if_valid_index(i, rows[i].lookup_rng_chk_6_counts); + polys.lookup_rng_chk_7_counts.set_if_valid_index(i, rows[i].lookup_rng_chk_7_counts); + polys.lookup_pow_2_0_counts.set_if_valid_index(i, rows[i].lookup_pow_2_0_counts); + polys.lookup_pow_2_1_counts.set_if_valid_index(i, rows[i].lookup_pow_2_1_counts); + polys.lookup_byte_lengths_counts.set_if_valid_index(i, rows[i].lookup_byte_lengths_counts); + polys.lookup_byte_operations_counts.set_if_valid_index(i, rows[i].lookup_byte_operations_counts); + polys.lookup_opcode_gas_counts.set_if_valid_index(i, rows[i].lookup_opcode_gas_counts); + polys.kernel_output_lookup_counts.set_if_valid_index(i, rows[i].kernel_output_lookup_counts); + polys.lookup_into_kernel_counts.set_if_valid_index(i, rows[i].lookup_into_kernel_counts); + polys.lookup_cd_value_counts.set_if_valid_index(i, rows[i].lookup_cd_value_counts); + polys.lookup_ret_value_counts.set_if_valid_index(i, rows[i].lookup_ret_value_counts); + polys.incl_main_tag_err_counts.set_if_valid_index(i, rows[i].incl_main_tag_err_counts); + polys.incl_mem_tag_err_counts.set_if_valid_index(i, rows[i].incl_mem_tag_err_counts); } for (auto [shifted, to_be_shifted] : zip_view(polys.get_shifted(), polys.get_to_be_shifted())) { diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.cpp index f54c2b41054..e9520fbff1c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.cpp @@ -189,564 +189,563 @@ AvmFlavor::AllConstRefValues::AllConstRefValues( , main_sel_op_cast(il[181]) , main_sel_op_chain_id(il[182]) , main_sel_op_cmov(il[183]) - , main_sel_op_coinbase(il[184]) - , main_sel_op_dagasleft(il[185]) - , main_sel_op_div(il[186]) - , main_sel_op_ecadd(il[187]) - , main_sel_op_emit_l2_to_l1_msg(il[188]) - , main_sel_op_emit_note_hash(il[189]) - , main_sel_op_emit_nullifier(il[190]) - , main_sel_op_emit_unencrypted_log(il[191]) - , main_sel_op_eq(il[192]) - , main_sel_op_external_call(il[193]) - , main_sel_op_external_return(il[194]) - , main_sel_op_external_revert(il[195]) - , main_sel_op_fdiv(il[196]) - , main_sel_op_fee_per_da_gas(il[197]) - , main_sel_op_fee_per_l2_gas(il[198]) - , main_sel_op_function_selector(il[199]) - , main_sel_op_get_contract_instance(il[200]) - , main_sel_op_internal_call(il[201]) - , main_sel_op_internal_return(il[202]) - , main_sel_op_jump(il[203]) - , main_sel_op_jumpi(il[204]) - , main_sel_op_keccak(il[205]) - , main_sel_op_l1_to_l2_msg_exists(il[206]) - , main_sel_op_l2gasleft(il[207]) - , main_sel_op_lt(il[208]) - , main_sel_op_lte(il[209]) - , main_sel_op_mov(il[210]) - , main_sel_op_msm(il[211]) - , main_sel_op_mul(il[212]) - , main_sel_op_not(il[213]) - , main_sel_op_note_hash_exists(il[214]) - , main_sel_op_nullifier_exists(il[215]) - , main_sel_op_or(il[216]) - , main_sel_op_pedersen(il[217]) - , main_sel_op_pedersen_commit(il[218]) - , main_sel_op_poseidon2(il[219]) - , main_sel_op_radix_le(il[220]) - , main_sel_op_sender(il[221]) - , main_sel_op_set(il[222]) - , main_sel_op_sha256(il[223]) - , main_sel_op_shl(il[224]) - , main_sel_op_shr(il[225]) - , main_sel_op_sload(il[226]) - , main_sel_op_sstore(il[227]) - , main_sel_op_storage_address(il[228]) - , main_sel_op_sub(il[229]) - , main_sel_op_timestamp(il[230]) - , main_sel_op_transaction_fee(il[231]) - , main_sel_op_version(il[232]) - , main_sel_op_xor(il[233]) - , main_sel_q_kernel_lookup(il[234]) - , main_sel_q_kernel_output_lookup(il[235]) - , main_sel_resolve_ind_addr_a(il[236]) - , main_sel_resolve_ind_addr_b(il[237]) - , main_sel_resolve_ind_addr_c(il[238]) - , main_sel_resolve_ind_addr_d(il[239]) - , main_sel_returndata(il[240]) - , main_sel_rng_16(il[241]) - , main_sel_rng_8(il[242]) - , main_sel_slice_gadget(il[243]) - , main_side_effect_counter(il[244]) - , main_sload_write_offset(il[245]) - , main_space_id(il[246]) - , main_sstore_write_offset(il[247]) - , main_tag_err(il[248]) - , main_w_in_tag(il[249]) - , mem_addr(il[250]) - , mem_clk(il[251]) - , mem_diff(il[252]) - , mem_glob_addr(il[253]) - , mem_last(il[254]) - , mem_lastAccess(il[255]) - , mem_one_min_inv(il[256]) - , mem_r_in_tag(il[257]) - , mem_rw(il[258]) - , mem_sel_mem(il[259]) - , mem_sel_mov_ia_to_ic(il[260]) - , mem_sel_mov_ib_to_ic(il[261]) - , mem_sel_op_a(il[262]) - , mem_sel_op_b(il[263]) - , mem_sel_op_c(il[264]) - , mem_sel_op_cmov(il[265]) - , mem_sel_op_d(il[266]) - , mem_sel_op_poseidon_read_a(il[267]) - , mem_sel_op_poseidon_read_b(il[268]) - , mem_sel_op_poseidon_read_c(il[269]) - , mem_sel_op_poseidon_read_d(il[270]) - , mem_sel_op_poseidon_write_a(il[271]) - , mem_sel_op_poseidon_write_b(il[272]) - , mem_sel_op_poseidon_write_c(il[273]) - , mem_sel_op_poseidon_write_d(il[274]) - , mem_sel_op_slice(il[275]) - , mem_sel_resolve_ind_addr_a(il[276]) - , mem_sel_resolve_ind_addr_b(il[277]) - , mem_sel_resolve_ind_addr_c(il[278]) - , mem_sel_resolve_ind_addr_d(il[279]) - , mem_sel_rng_chk(il[280]) - , mem_skip_check_tag(il[281]) - , mem_space_id(il[282]) - , mem_tag(il[283]) - , mem_tag_err(il[284]) - , mem_tsp(il[285]) - , mem_val(il[286]) - , mem_w_in_tag(il[287]) - , pedersen_clk(il[288]) - , pedersen_input(il[289]) - , pedersen_output(il[290]) - , pedersen_sel_pedersen(il[291]) - , poseidon2_B_10_0(il[292]) - , poseidon2_B_10_1(il[293]) - , poseidon2_B_10_2(il[294]) - , poseidon2_B_10_3(il[295]) - , poseidon2_B_11_0(il[296]) - , poseidon2_B_11_1(il[297]) - , poseidon2_B_11_2(il[298]) - , poseidon2_B_11_3(il[299]) - , poseidon2_B_12_0(il[300]) - , poseidon2_B_12_1(il[301]) - , poseidon2_B_12_2(il[302]) - , poseidon2_B_12_3(il[303]) - , poseidon2_B_13_0(il[304]) - , poseidon2_B_13_1(il[305]) - , poseidon2_B_13_2(il[306]) - , poseidon2_B_13_3(il[307]) - , poseidon2_B_14_0(il[308]) - , poseidon2_B_14_1(il[309]) - , poseidon2_B_14_2(il[310]) - , poseidon2_B_14_3(il[311]) - , poseidon2_B_15_0(il[312]) - , poseidon2_B_15_1(il[313]) - , poseidon2_B_15_2(il[314]) - , poseidon2_B_15_3(il[315]) - , poseidon2_B_16_0(il[316]) - , poseidon2_B_16_1(il[317]) - , poseidon2_B_16_2(il[318]) - , poseidon2_B_16_3(il[319]) - , poseidon2_B_17_0(il[320]) - , poseidon2_B_17_1(il[321]) - , poseidon2_B_17_2(il[322]) - , poseidon2_B_17_3(il[323]) - , poseidon2_B_18_0(il[324]) - , poseidon2_B_18_1(il[325]) - , poseidon2_B_18_2(il[326]) - , poseidon2_B_18_3(il[327]) - , poseidon2_B_19_0(il[328]) - , poseidon2_B_19_1(il[329]) - , poseidon2_B_19_2(il[330]) - , poseidon2_B_19_3(il[331]) - , poseidon2_B_20_0(il[332]) - , poseidon2_B_20_1(il[333]) - , poseidon2_B_20_2(il[334]) - , poseidon2_B_20_3(il[335]) - , poseidon2_B_21_0(il[336]) - , poseidon2_B_21_1(il[337]) - , poseidon2_B_21_2(il[338]) - , poseidon2_B_21_3(il[339]) - , poseidon2_B_22_0(il[340]) - , poseidon2_B_22_1(il[341]) - , poseidon2_B_22_2(il[342]) - , poseidon2_B_22_3(il[343]) - , poseidon2_B_23_0(il[344]) - , poseidon2_B_23_1(il[345]) - , poseidon2_B_23_2(il[346]) - , poseidon2_B_23_3(il[347]) - , poseidon2_B_24_0(il[348]) - , poseidon2_B_24_1(il[349]) - , poseidon2_B_24_2(il[350]) - , poseidon2_B_24_3(il[351]) - , poseidon2_B_25_0(il[352]) - , poseidon2_B_25_1(il[353]) - , poseidon2_B_25_2(il[354]) - , poseidon2_B_25_3(il[355]) - , poseidon2_B_26_0(il[356]) - , poseidon2_B_26_1(il[357]) - , poseidon2_B_26_2(il[358]) - , poseidon2_B_26_3(il[359]) - , poseidon2_B_27_0(il[360]) - , poseidon2_B_27_1(il[361]) - , poseidon2_B_27_2(il[362]) - , poseidon2_B_27_3(il[363]) - , poseidon2_B_28_0(il[364]) - , poseidon2_B_28_1(il[365]) - , poseidon2_B_28_2(il[366]) - , poseidon2_B_28_3(il[367]) - , poseidon2_B_29_0(il[368]) - , poseidon2_B_29_1(il[369]) - , poseidon2_B_29_2(il[370]) - , poseidon2_B_29_3(il[371]) - , poseidon2_B_30_0(il[372]) - , poseidon2_B_30_1(il[373]) - , poseidon2_B_30_2(il[374]) - , poseidon2_B_30_3(il[375]) - , poseidon2_B_31_0(il[376]) - , poseidon2_B_31_1(il[377]) - , poseidon2_B_31_2(il[378]) - , poseidon2_B_31_3(il[379]) - , poseidon2_B_32_0(il[380]) - , poseidon2_B_32_1(il[381]) - , poseidon2_B_32_2(il[382]) - , poseidon2_B_32_3(il[383]) - , poseidon2_B_33_0(il[384]) - , poseidon2_B_33_1(il[385]) - , poseidon2_B_33_2(il[386]) - , poseidon2_B_33_3(il[387]) - , poseidon2_B_34_0(il[388]) - , poseidon2_B_34_1(il[389]) - , poseidon2_B_34_2(il[390]) - , poseidon2_B_34_3(il[391]) - , poseidon2_B_35_0(il[392]) - , poseidon2_B_35_1(il[393]) - , poseidon2_B_35_2(il[394]) - , poseidon2_B_35_3(il[395]) - , poseidon2_B_36_0(il[396]) - , poseidon2_B_36_1(il[397]) - , poseidon2_B_36_2(il[398]) - , poseidon2_B_36_3(il[399]) - , poseidon2_B_37_0(il[400]) - , poseidon2_B_37_1(il[401]) - , poseidon2_B_37_2(il[402]) - , poseidon2_B_37_3(il[403]) - , poseidon2_B_38_0(il[404]) - , poseidon2_B_38_1(il[405]) - , poseidon2_B_38_2(il[406]) - , poseidon2_B_38_3(il[407]) - , poseidon2_B_39_0(il[408]) - , poseidon2_B_39_1(il[409]) - , poseidon2_B_39_2(il[410]) - , poseidon2_B_39_3(il[411]) - , poseidon2_B_40_0(il[412]) - , poseidon2_B_40_1(il[413]) - , poseidon2_B_40_2(il[414]) - , poseidon2_B_40_3(il[415]) - , poseidon2_B_41_0(il[416]) - , poseidon2_B_41_1(il[417]) - , poseidon2_B_41_2(il[418]) - , poseidon2_B_41_3(il[419]) - , poseidon2_B_42_0(il[420]) - , poseidon2_B_42_1(il[421]) - , poseidon2_B_42_2(il[422]) - , poseidon2_B_42_3(il[423]) - , poseidon2_B_43_0(il[424]) - , poseidon2_B_43_1(il[425]) - , poseidon2_B_43_2(il[426]) - , poseidon2_B_43_3(il[427]) - , poseidon2_B_44_0(il[428]) - , poseidon2_B_44_1(il[429]) - , poseidon2_B_44_2(il[430]) - , poseidon2_B_44_3(il[431]) - , poseidon2_B_45_0(il[432]) - , poseidon2_B_45_1(il[433]) - , poseidon2_B_45_2(il[434]) - , poseidon2_B_45_3(il[435]) - , poseidon2_B_46_0(il[436]) - , poseidon2_B_46_1(il[437]) - , poseidon2_B_46_2(il[438]) - , poseidon2_B_46_3(il[439]) - , poseidon2_B_47_0(il[440]) - , poseidon2_B_47_1(il[441]) - , poseidon2_B_47_2(il[442]) - , poseidon2_B_47_3(il[443]) - , poseidon2_B_48_0(il[444]) - , poseidon2_B_48_1(il[445]) - , poseidon2_B_48_2(il[446]) - , poseidon2_B_48_3(il[447]) - , poseidon2_B_49_0(il[448]) - , poseidon2_B_49_1(il[449]) - , poseidon2_B_49_2(il[450]) - , poseidon2_B_49_3(il[451]) - , poseidon2_B_4_0(il[452]) - , poseidon2_B_4_1(il[453]) - , poseidon2_B_4_2(il[454]) - , poseidon2_B_4_3(il[455]) - , poseidon2_B_50_0(il[456]) - , poseidon2_B_50_1(il[457]) - , poseidon2_B_50_2(il[458]) - , poseidon2_B_50_3(il[459]) - , poseidon2_B_51_0(il[460]) - , poseidon2_B_51_1(il[461]) - , poseidon2_B_51_2(il[462]) - , poseidon2_B_51_3(il[463]) - , poseidon2_B_52_0(il[464]) - , poseidon2_B_52_1(il[465]) - , poseidon2_B_52_2(il[466]) - , poseidon2_B_52_3(il[467]) - , poseidon2_B_53_0(il[468]) - , poseidon2_B_53_1(il[469]) - , poseidon2_B_53_2(il[470]) - , poseidon2_B_53_3(il[471]) - , poseidon2_B_54_0(il[472]) - , poseidon2_B_54_1(il[473]) - , poseidon2_B_54_2(il[474]) - , poseidon2_B_54_3(il[475]) - , poseidon2_B_55_0(il[476]) - , poseidon2_B_55_1(il[477]) - , poseidon2_B_55_2(il[478]) - , poseidon2_B_55_3(il[479]) - , poseidon2_B_56_0(il[480]) - , poseidon2_B_56_1(il[481]) - , poseidon2_B_56_2(il[482]) - , poseidon2_B_56_3(il[483]) - , poseidon2_B_57_0(il[484]) - , poseidon2_B_57_1(il[485]) - , poseidon2_B_57_2(il[486]) - , poseidon2_B_57_3(il[487]) - , poseidon2_B_58_0(il[488]) - , poseidon2_B_58_1(il[489]) - , poseidon2_B_58_2(il[490]) - , poseidon2_B_58_3(il[491]) - , poseidon2_B_59_0(il[492]) - , poseidon2_B_59_1(il[493]) - , poseidon2_B_59_2(il[494]) - , poseidon2_B_59_3(il[495]) - , poseidon2_B_5_0(il[496]) - , poseidon2_B_5_1(il[497]) - , poseidon2_B_5_2(il[498]) - , poseidon2_B_5_3(il[499]) - , poseidon2_B_6_0(il[500]) - , poseidon2_B_6_1(il[501]) - , poseidon2_B_6_2(il[502]) - , poseidon2_B_6_3(il[503]) - , poseidon2_B_7_0(il[504]) - , poseidon2_B_7_1(il[505]) - , poseidon2_B_7_2(il[506]) - , poseidon2_B_7_3(il[507]) - , poseidon2_B_8_0(il[508]) - , poseidon2_B_8_1(il[509]) - , poseidon2_B_8_2(il[510]) - , poseidon2_B_8_3(il[511]) - , poseidon2_B_9_0(il[512]) - , poseidon2_B_9_1(il[513]) - , poseidon2_B_9_2(il[514]) - , poseidon2_B_9_3(il[515]) - , poseidon2_EXT_LAYER_4(il[516]) - , poseidon2_EXT_LAYER_5(il[517]) - , poseidon2_EXT_LAYER_6(il[518]) - , poseidon2_EXT_LAYER_7(il[519]) - , poseidon2_T_0_4(il[520]) - , poseidon2_T_0_5(il[521]) - , poseidon2_T_0_6(il[522]) - , poseidon2_T_0_7(il[523]) - , poseidon2_T_1_4(il[524]) - , poseidon2_T_1_5(il[525]) - , poseidon2_T_1_6(il[526]) - , poseidon2_T_1_7(il[527]) - , poseidon2_T_2_4(il[528]) - , poseidon2_T_2_5(il[529]) - , poseidon2_T_2_6(il[530]) - , poseidon2_T_2_7(il[531]) - , poseidon2_T_3_4(il[532]) - , poseidon2_T_3_5(il[533]) - , poseidon2_T_3_6(il[534]) - , poseidon2_T_3_7(il[535]) - , poseidon2_T_60_4(il[536]) - , poseidon2_T_60_5(il[537]) - , poseidon2_T_60_6(il[538]) - , poseidon2_T_60_7(il[539]) - , poseidon2_T_61_4(il[540]) - , poseidon2_T_61_5(il[541]) - , poseidon2_T_61_6(il[542]) - , poseidon2_T_61_7(il[543]) - , poseidon2_T_62_4(il[544]) - , poseidon2_T_62_5(il[545]) - , poseidon2_T_62_6(il[546]) - , poseidon2_T_62_7(il[547]) - , poseidon2_T_63_4(il[548]) - , poseidon2_T_63_5(il[549]) - , poseidon2_T_63_6(il[550]) - , poseidon2_T_63_7(il[551]) - , poseidon2_a_0(il[552]) - , poseidon2_a_1(il[553]) - , poseidon2_a_2(il[554]) - , poseidon2_a_3(il[555]) - , poseidon2_b_0(il[556]) - , poseidon2_b_1(il[557]) - , poseidon2_b_2(il[558]) - , poseidon2_b_3(il[559]) - , poseidon2_clk(il[560]) - , poseidon2_input_addr(il[561]) - , poseidon2_mem_addr_read_a(il[562]) - , poseidon2_mem_addr_read_b(il[563]) - , poseidon2_mem_addr_read_c(il[564]) - , poseidon2_mem_addr_read_d(il[565]) - , poseidon2_mem_addr_write_a(il[566]) - , poseidon2_mem_addr_write_b(il[567]) - , poseidon2_mem_addr_write_c(il[568]) - , poseidon2_mem_addr_write_d(il[569]) - , poseidon2_output_addr(il[570]) - , poseidon2_sel_poseidon_perm(il[571]) - , range_check_alu_rng_chk(il[572]) - , range_check_clk(il[573]) - , range_check_cmp_hi_bits_rng_chk(il[574]) - , range_check_cmp_lo_bits_rng_chk(il[575]) - , range_check_dyn_diff(il[576]) - , range_check_dyn_rng_chk_bits(il[577]) - , range_check_dyn_rng_chk_pow_2(il[578]) - , range_check_gas_da_rng_chk(il[579]) - , range_check_gas_l2_rng_chk(il[580]) - , range_check_is_lte_u112(il[581]) - , range_check_is_lte_u128(il[582]) - , range_check_is_lte_u16(il[583]) - , range_check_is_lte_u32(il[584]) - , range_check_is_lte_u48(il[585]) - , range_check_is_lte_u64(il[586]) - , range_check_is_lte_u80(il[587]) - , range_check_is_lte_u96(il[588]) - , range_check_mem_rng_chk(il[589]) - , range_check_rng_chk_bits(il[590]) - , range_check_sel_lookup_0(il[591]) - , range_check_sel_lookup_1(il[592]) - , range_check_sel_lookup_2(il[593]) - , range_check_sel_lookup_3(il[594]) - , range_check_sel_lookup_4(il[595]) - , range_check_sel_lookup_5(il[596]) - , range_check_sel_lookup_6(il[597]) - , range_check_sel_rng_chk(il[598]) - , range_check_u16_r0(il[599]) - , range_check_u16_r1(il[600]) - , range_check_u16_r2(il[601]) - , range_check_u16_r3(il[602]) - , range_check_u16_r4(il[603]) - , range_check_u16_r5(il[604]) - , range_check_u16_r6(il[605]) - , range_check_u16_r7(il[606]) - , range_check_value(il[607]) - , sha256_clk(il[608]) - , sha256_input(il[609]) - , sha256_output(il[610]) - , sha256_sel_sha256_compression(il[611]) - , sha256_state(il[612]) - , slice_addr(il[613]) - , slice_clk(il[614]) - , slice_cnt(il[615]) - , slice_col_offset(il[616]) - , slice_one_min_inv(il[617]) - , slice_sel_cd_cpy(il[618]) - , slice_sel_mem_active(il[619]) - , slice_sel_return(il[620]) - , slice_sel_start(il[621]) - , slice_space_id(il[622]) - , slice_val(il[623]) - , lookup_rng_chk_pow_2_counts(il[624]) - , lookup_rng_chk_diff_counts(il[625]) - , lookup_rng_chk_0_counts(il[626]) - , lookup_rng_chk_1_counts(il[627]) - , lookup_rng_chk_2_counts(il[628]) - , lookup_rng_chk_3_counts(il[629]) - , lookup_rng_chk_4_counts(il[630]) - , lookup_rng_chk_5_counts(il[631]) - , lookup_rng_chk_6_counts(il[632]) - , lookup_rng_chk_7_counts(il[633]) - , lookup_pow_2_0_counts(il[634]) - , lookup_pow_2_1_counts(il[635]) - , lookup_byte_lengths_counts(il[636]) - , lookup_byte_operations_counts(il[637]) - , lookup_opcode_gas_counts(il[638]) - , kernel_output_lookup_counts(il[639]) - , lookup_into_kernel_counts(il[640]) - , lookup_cd_value_counts(il[641]) - , lookup_ret_value_counts(il[642]) - , incl_main_tag_err_counts(il[643]) - , incl_mem_tag_err_counts(il[644]) - , perm_rng_mem_inv(il[645]) - , perm_rng_cmp_lo_inv(il[646]) - , perm_rng_cmp_hi_inv(il[647]) - , perm_rng_alu_inv(il[648]) - , perm_cmp_alu_inv(il[649]) - , perm_rng_gas_l2_inv(il[650]) - , perm_rng_gas_da_inv(il[651]) - , perm_pos_mem_read_a_inv(il[652]) - , perm_pos_mem_read_b_inv(il[653]) - , perm_pos_mem_read_c_inv(il[654]) - , perm_pos_mem_read_d_inv(il[655]) - , perm_pos_mem_write_a_inv(il[656]) - , perm_pos_mem_write_b_inv(il[657]) - , perm_pos_mem_write_c_inv(il[658]) - , perm_pos_mem_write_d_inv(il[659]) - , perm_slice_mem_inv(il[660]) - , perm_main_alu_inv(il[661]) - , perm_main_bin_inv(il[662]) - , perm_main_conv_inv(il[663]) - , perm_main_pos2_perm_inv(il[664]) - , perm_main_pedersen_inv(il[665]) - , perm_main_slice_inv(il[666]) - , perm_main_mem_a_inv(il[667]) - , perm_main_mem_b_inv(il[668]) - , perm_main_mem_c_inv(il[669]) - , perm_main_mem_d_inv(il[670]) - , perm_main_mem_ind_addr_a_inv(il[671]) - , perm_main_mem_ind_addr_b_inv(il[672]) - , perm_main_mem_ind_addr_c_inv(il[673]) - , perm_main_mem_ind_addr_d_inv(il[674]) - , lookup_rng_chk_pow_2_inv(il[675]) - , lookup_rng_chk_diff_inv(il[676]) - , lookup_rng_chk_0_inv(il[677]) - , lookup_rng_chk_1_inv(il[678]) - , lookup_rng_chk_2_inv(il[679]) - , lookup_rng_chk_3_inv(il[680]) - , lookup_rng_chk_4_inv(il[681]) - , lookup_rng_chk_5_inv(il[682]) - , lookup_rng_chk_6_inv(il[683]) - , lookup_rng_chk_7_inv(il[684]) - , lookup_pow_2_0_inv(il[685]) - , lookup_pow_2_1_inv(il[686]) - , lookup_byte_lengths_inv(il[687]) - , lookup_byte_operations_inv(il[688]) - , lookup_opcode_gas_inv(il[689]) - , kernel_output_lookup_inv(il[690]) - , lookup_into_kernel_inv(il[691]) - , lookup_cd_value_inv(il[692]) - , lookup_ret_value_inv(il[693]) - , incl_main_tag_err_inv(il[694]) - , incl_mem_tag_err_inv(il[695]) - , binary_acc_ia_shift(il[696]) - , binary_acc_ib_shift(il[697]) - , binary_acc_ic_shift(il[698]) - , binary_mem_tag_ctr_shift(il[699]) - , binary_op_id_shift(il[700]) - , cmp_a_hi_shift(il[701]) - , cmp_a_lo_shift(il[702]) - , cmp_b_hi_shift(il[703]) - , cmp_b_lo_shift(il[704]) - , cmp_cmp_rng_ctr_shift(il[705]) - , cmp_op_gt_shift(il[706]) - , cmp_p_sub_a_hi_shift(il[707]) - , cmp_p_sub_a_lo_shift(il[708]) - , cmp_p_sub_b_hi_shift(il[709]) - , cmp_p_sub_b_lo_shift(il[710]) - , cmp_sel_rng_chk_shift(il[711]) - , main_da_gas_remaining_shift(il[712]) - , main_emit_l2_to_l1_msg_write_offset_shift(il[713]) - , main_emit_note_hash_write_offset_shift(il[714]) - , main_emit_nullifier_write_offset_shift(il[715]) - , main_emit_unencrypted_log_write_offset_shift(il[716]) - , main_internal_return_ptr_shift(il[717]) - , main_l1_to_l2_msg_exists_write_offset_shift(il[718]) - , main_l2_gas_remaining_shift(il[719]) - , main_note_hash_exist_write_offset_shift(il[720]) - , main_nullifier_exists_write_offset_shift(il[721]) - , main_nullifier_non_exists_write_offset_shift(il[722]) - , main_pc_shift(il[723]) - , main_sel_execution_row_shift(il[724]) - , main_sload_write_offset_shift(il[725]) - , main_sstore_write_offset_shift(il[726]) - , mem_glob_addr_shift(il[727]) - , mem_rw_shift(il[728]) - , mem_sel_mem_shift(il[729]) - , mem_tag_shift(il[730]) - , mem_tsp_shift(il[731]) - , mem_val_shift(il[732]) - , slice_addr_shift(il[733]) - , slice_clk_shift(il[734]) - , slice_cnt_shift(il[735]) - , slice_col_offset_shift(il[736]) - , slice_sel_cd_cpy_shift(il[737]) - , slice_sel_mem_active_shift(il[738]) - , slice_sel_return_shift(il[739]) - , slice_sel_start_shift(il[740]) - , slice_space_id_shift(il[741]) + , main_sel_op_dagasleft(il[184]) + , main_sel_op_div(il[185]) + , main_sel_op_ecadd(il[186]) + , main_sel_op_emit_l2_to_l1_msg(il[187]) + , main_sel_op_emit_note_hash(il[188]) + , main_sel_op_emit_nullifier(il[189]) + , main_sel_op_emit_unencrypted_log(il[190]) + , main_sel_op_eq(il[191]) + , main_sel_op_external_call(il[192]) + , main_sel_op_external_return(il[193]) + , main_sel_op_external_revert(il[194]) + , main_sel_op_fdiv(il[195]) + , main_sel_op_fee_per_da_gas(il[196]) + , main_sel_op_fee_per_l2_gas(il[197]) + , main_sel_op_function_selector(il[198]) + , main_sel_op_get_contract_instance(il[199]) + , main_sel_op_internal_call(il[200]) + , main_sel_op_internal_return(il[201]) + , main_sel_op_jump(il[202]) + , main_sel_op_jumpi(il[203]) + , main_sel_op_keccak(il[204]) + , main_sel_op_l1_to_l2_msg_exists(il[205]) + , main_sel_op_l2gasleft(il[206]) + , main_sel_op_lt(il[207]) + , main_sel_op_lte(il[208]) + , main_sel_op_mov(il[209]) + , main_sel_op_msm(il[210]) + , main_sel_op_mul(il[211]) + , main_sel_op_not(il[212]) + , main_sel_op_note_hash_exists(il[213]) + , main_sel_op_nullifier_exists(il[214]) + , main_sel_op_or(il[215]) + , main_sel_op_pedersen(il[216]) + , main_sel_op_pedersen_commit(il[217]) + , main_sel_op_poseidon2(il[218]) + , main_sel_op_radix_le(il[219]) + , main_sel_op_sender(il[220]) + , main_sel_op_set(il[221]) + , main_sel_op_sha256(il[222]) + , main_sel_op_shl(il[223]) + , main_sel_op_shr(il[224]) + , main_sel_op_sload(il[225]) + , main_sel_op_sstore(il[226]) + , main_sel_op_storage_address(il[227]) + , main_sel_op_sub(il[228]) + , main_sel_op_timestamp(il[229]) + , main_sel_op_transaction_fee(il[230]) + , main_sel_op_version(il[231]) + , main_sel_op_xor(il[232]) + , main_sel_q_kernel_lookup(il[233]) + , main_sel_q_kernel_output_lookup(il[234]) + , main_sel_resolve_ind_addr_a(il[235]) + , main_sel_resolve_ind_addr_b(il[236]) + , main_sel_resolve_ind_addr_c(il[237]) + , main_sel_resolve_ind_addr_d(il[238]) + , main_sel_returndata(il[239]) + , main_sel_rng_16(il[240]) + , main_sel_rng_8(il[241]) + , main_sel_slice_gadget(il[242]) + , main_side_effect_counter(il[243]) + , main_sload_write_offset(il[244]) + , main_space_id(il[245]) + , main_sstore_write_offset(il[246]) + , main_tag_err(il[247]) + , main_w_in_tag(il[248]) + , mem_addr(il[249]) + , mem_clk(il[250]) + , mem_diff(il[251]) + , mem_glob_addr(il[252]) + , mem_last(il[253]) + , mem_lastAccess(il[254]) + , mem_one_min_inv(il[255]) + , mem_r_in_tag(il[256]) + , mem_rw(il[257]) + , mem_sel_mem(il[258]) + , mem_sel_mov_ia_to_ic(il[259]) + , mem_sel_mov_ib_to_ic(il[260]) + , mem_sel_op_a(il[261]) + , mem_sel_op_b(il[262]) + , mem_sel_op_c(il[263]) + , mem_sel_op_cmov(il[264]) + , mem_sel_op_d(il[265]) + , mem_sel_op_poseidon_read_a(il[266]) + , mem_sel_op_poseidon_read_b(il[267]) + , mem_sel_op_poseidon_read_c(il[268]) + , mem_sel_op_poseidon_read_d(il[269]) + , mem_sel_op_poseidon_write_a(il[270]) + , mem_sel_op_poseidon_write_b(il[271]) + , mem_sel_op_poseidon_write_c(il[272]) + , mem_sel_op_poseidon_write_d(il[273]) + , mem_sel_op_slice(il[274]) + , mem_sel_resolve_ind_addr_a(il[275]) + , mem_sel_resolve_ind_addr_b(il[276]) + , mem_sel_resolve_ind_addr_c(il[277]) + , mem_sel_resolve_ind_addr_d(il[278]) + , mem_sel_rng_chk(il[279]) + , mem_skip_check_tag(il[280]) + , mem_space_id(il[281]) + , mem_tag(il[282]) + , mem_tag_err(il[283]) + , mem_tsp(il[284]) + , mem_val(il[285]) + , mem_w_in_tag(il[286]) + , pedersen_clk(il[287]) + , pedersen_input(il[288]) + , pedersen_output(il[289]) + , pedersen_sel_pedersen(il[290]) + , poseidon2_B_10_0(il[291]) + , poseidon2_B_10_1(il[292]) + , poseidon2_B_10_2(il[293]) + , poseidon2_B_10_3(il[294]) + , poseidon2_B_11_0(il[295]) + , poseidon2_B_11_1(il[296]) + , poseidon2_B_11_2(il[297]) + , poseidon2_B_11_3(il[298]) + , poseidon2_B_12_0(il[299]) + , poseidon2_B_12_1(il[300]) + , poseidon2_B_12_2(il[301]) + , poseidon2_B_12_3(il[302]) + , poseidon2_B_13_0(il[303]) + , poseidon2_B_13_1(il[304]) + , poseidon2_B_13_2(il[305]) + , poseidon2_B_13_3(il[306]) + , poseidon2_B_14_0(il[307]) + , poseidon2_B_14_1(il[308]) + , poseidon2_B_14_2(il[309]) + , poseidon2_B_14_3(il[310]) + , poseidon2_B_15_0(il[311]) + , poseidon2_B_15_1(il[312]) + , poseidon2_B_15_2(il[313]) + , poseidon2_B_15_3(il[314]) + , poseidon2_B_16_0(il[315]) + , poseidon2_B_16_1(il[316]) + , poseidon2_B_16_2(il[317]) + , poseidon2_B_16_3(il[318]) + , poseidon2_B_17_0(il[319]) + , poseidon2_B_17_1(il[320]) + , poseidon2_B_17_2(il[321]) + , poseidon2_B_17_3(il[322]) + , poseidon2_B_18_0(il[323]) + , poseidon2_B_18_1(il[324]) + , poseidon2_B_18_2(il[325]) + , poseidon2_B_18_3(il[326]) + , poseidon2_B_19_0(il[327]) + , poseidon2_B_19_1(il[328]) + , poseidon2_B_19_2(il[329]) + , poseidon2_B_19_3(il[330]) + , poseidon2_B_20_0(il[331]) + , poseidon2_B_20_1(il[332]) + , poseidon2_B_20_2(il[333]) + , poseidon2_B_20_3(il[334]) + , poseidon2_B_21_0(il[335]) + , poseidon2_B_21_1(il[336]) + , poseidon2_B_21_2(il[337]) + , poseidon2_B_21_3(il[338]) + , poseidon2_B_22_0(il[339]) + , poseidon2_B_22_1(il[340]) + , poseidon2_B_22_2(il[341]) + , poseidon2_B_22_3(il[342]) + , poseidon2_B_23_0(il[343]) + , poseidon2_B_23_1(il[344]) + , poseidon2_B_23_2(il[345]) + , poseidon2_B_23_3(il[346]) + , poseidon2_B_24_0(il[347]) + , poseidon2_B_24_1(il[348]) + , poseidon2_B_24_2(il[349]) + , poseidon2_B_24_3(il[350]) + , poseidon2_B_25_0(il[351]) + , poseidon2_B_25_1(il[352]) + , poseidon2_B_25_2(il[353]) + , poseidon2_B_25_3(il[354]) + , poseidon2_B_26_0(il[355]) + , poseidon2_B_26_1(il[356]) + , poseidon2_B_26_2(il[357]) + , poseidon2_B_26_3(il[358]) + , poseidon2_B_27_0(il[359]) + , poseidon2_B_27_1(il[360]) + , poseidon2_B_27_2(il[361]) + , poseidon2_B_27_3(il[362]) + , poseidon2_B_28_0(il[363]) + , poseidon2_B_28_1(il[364]) + , poseidon2_B_28_2(il[365]) + , poseidon2_B_28_3(il[366]) + , poseidon2_B_29_0(il[367]) + , poseidon2_B_29_1(il[368]) + , poseidon2_B_29_2(il[369]) + , poseidon2_B_29_3(il[370]) + , poseidon2_B_30_0(il[371]) + , poseidon2_B_30_1(il[372]) + , poseidon2_B_30_2(il[373]) + , poseidon2_B_30_3(il[374]) + , poseidon2_B_31_0(il[375]) + , poseidon2_B_31_1(il[376]) + , poseidon2_B_31_2(il[377]) + , poseidon2_B_31_3(il[378]) + , poseidon2_B_32_0(il[379]) + , poseidon2_B_32_1(il[380]) + , poseidon2_B_32_2(il[381]) + , poseidon2_B_32_3(il[382]) + , poseidon2_B_33_0(il[383]) + , poseidon2_B_33_1(il[384]) + , poseidon2_B_33_2(il[385]) + , poseidon2_B_33_3(il[386]) + , poseidon2_B_34_0(il[387]) + , poseidon2_B_34_1(il[388]) + , poseidon2_B_34_2(il[389]) + , poseidon2_B_34_3(il[390]) + , poseidon2_B_35_0(il[391]) + , poseidon2_B_35_1(il[392]) + , poseidon2_B_35_2(il[393]) + , poseidon2_B_35_3(il[394]) + , poseidon2_B_36_0(il[395]) + , poseidon2_B_36_1(il[396]) + , poseidon2_B_36_2(il[397]) + , poseidon2_B_36_3(il[398]) + , poseidon2_B_37_0(il[399]) + , poseidon2_B_37_1(il[400]) + , poseidon2_B_37_2(il[401]) + , poseidon2_B_37_3(il[402]) + , poseidon2_B_38_0(il[403]) + , poseidon2_B_38_1(il[404]) + , poseidon2_B_38_2(il[405]) + , poseidon2_B_38_3(il[406]) + , poseidon2_B_39_0(il[407]) + , poseidon2_B_39_1(il[408]) + , poseidon2_B_39_2(il[409]) + , poseidon2_B_39_3(il[410]) + , poseidon2_B_40_0(il[411]) + , poseidon2_B_40_1(il[412]) + , poseidon2_B_40_2(il[413]) + , poseidon2_B_40_3(il[414]) + , poseidon2_B_41_0(il[415]) + , poseidon2_B_41_1(il[416]) + , poseidon2_B_41_2(il[417]) + , poseidon2_B_41_3(il[418]) + , poseidon2_B_42_0(il[419]) + , poseidon2_B_42_1(il[420]) + , poseidon2_B_42_2(il[421]) + , poseidon2_B_42_3(il[422]) + , poseidon2_B_43_0(il[423]) + , poseidon2_B_43_1(il[424]) + , poseidon2_B_43_2(il[425]) + , poseidon2_B_43_3(il[426]) + , poseidon2_B_44_0(il[427]) + , poseidon2_B_44_1(il[428]) + , poseidon2_B_44_2(il[429]) + , poseidon2_B_44_3(il[430]) + , poseidon2_B_45_0(il[431]) + , poseidon2_B_45_1(il[432]) + , poseidon2_B_45_2(il[433]) + , poseidon2_B_45_3(il[434]) + , poseidon2_B_46_0(il[435]) + , poseidon2_B_46_1(il[436]) + , poseidon2_B_46_2(il[437]) + , poseidon2_B_46_3(il[438]) + , poseidon2_B_47_0(il[439]) + , poseidon2_B_47_1(il[440]) + , poseidon2_B_47_2(il[441]) + , poseidon2_B_47_3(il[442]) + , poseidon2_B_48_0(il[443]) + , poseidon2_B_48_1(il[444]) + , poseidon2_B_48_2(il[445]) + , poseidon2_B_48_3(il[446]) + , poseidon2_B_49_0(il[447]) + , poseidon2_B_49_1(il[448]) + , poseidon2_B_49_2(il[449]) + , poseidon2_B_49_3(il[450]) + , poseidon2_B_4_0(il[451]) + , poseidon2_B_4_1(il[452]) + , poseidon2_B_4_2(il[453]) + , poseidon2_B_4_3(il[454]) + , poseidon2_B_50_0(il[455]) + , poseidon2_B_50_1(il[456]) + , poseidon2_B_50_2(il[457]) + , poseidon2_B_50_3(il[458]) + , poseidon2_B_51_0(il[459]) + , poseidon2_B_51_1(il[460]) + , poseidon2_B_51_2(il[461]) + , poseidon2_B_51_3(il[462]) + , poseidon2_B_52_0(il[463]) + , poseidon2_B_52_1(il[464]) + , poseidon2_B_52_2(il[465]) + , poseidon2_B_52_3(il[466]) + , poseidon2_B_53_0(il[467]) + , poseidon2_B_53_1(il[468]) + , poseidon2_B_53_2(il[469]) + , poseidon2_B_53_3(il[470]) + , poseidon2_B_54_0(il[471]) + , poseidon2_B_54_1(il[472]) + , poseidon2_B_54_2(il[473]) + , poseidon2_B_54_3(il[474]) + , poseidon2_B_55_0(il[475]) + , poseidon2_B_55_1(il[476]) + , poseidon2_B_55_2(il[477]) + , poseidon2_B_55_3(il[478]) + , poseidon2_B_56_0(il[479]) + , poseidon2_B_56_1(il[480]) + , poseidon2_B_56_2(il[481]) + , poseidon2_B_56_3(il[482]) + , poseidon2_B_57_0(il[483]) + , poseidon2_B_57_1(il[484]) + , poseidon2_B_57_2(il[485]) + , poseidon2_B_57_3(il[486]) + , poseidon2_B_58_0(il[487]) + , poseidon2_B_58_1(il[488]) + , poseidon2_B_58_2(il[489]) + , poseidon2_B_58_3(il[490]) + , poseidon2_B_59_0(il[491]) + , poseidon2_B_59_1(il[492]) + , poseidon2_B_59_2(il[493]) + , poseidon2_B_59_3(il[494]) + , poseidon2_B_5_0(il[495]) + , poseidon2_B_5_1(il[496]) + , poseidon2_B_5_2(il[497]) + , poseidon2_B_5_3(il[498]) + , poseidon2_B_6_0(il[499]) + , poseidon2_B_6_1(il[500]) + , poseidon2_B_6_2(il[501]) + , poseidon2_B_6_3(il[502]) + , poseidon2_B_7_0(il[503]) + , poseidon2_B_7_1(il[504]) + , poseidon2_B_7_2(il[505]) + , poseidon2_B_7_3(il[506]) + , poseidon2_B_8_0(il[507]) + , poseidon2_B_8_1(il[508]) + , poseidon2_B_8_2(il[509]) + , poseidon2_B_8_3(il[510]) + , poseidon2_B_9_0(il[511]) + , poseidon2_B_9_1(il[512]) + , poseidon2_B_9_2(il[513]) + , poseidon2_B_9_3(il[514]) + , poseidon2_EXT_LAYER_4(il[515]) + , poseidon2_EXT_LAYER_5(il[516]) + , poseidon2_EXT_LAYER_6(il[517]) + , poseidon2_EXT_LAYER_7(il[518]) + , poseidon2_T_0_4(il[519]) + , poseidon2_T_0_5(il[520]) + , poseidon2_T_0_6(il[521]) + , poseidon2_T_0_7(il[522]) + , poseidon2_T_1_4(il[523]) + , poseidon2_T_1_5(il[524]) + , poseidon2_T_1_6(il[525]) + , poseidon2_T_1_7(il[526]) + , poseidon2_T_2_4(il[527]) + , poseidon2_T_2_5(il[528]) + , poseidon2_T_2_6(il[529]) + , poseidon2_T_2_7(il[530]) + , poseidon2_T_3_4(il[531]) + , poseidon2_T_3_5(il[532]) + , poseidon2_T_3_6(il[533]) + , poseidon2_T_3_7(il[534]) + , poseidon2_T_60_4(il[535]) + , poseidon2_T_60_5(il[536]) + , poseidon2_T_60_6(il[537]) + , poseidon2_T_60_7(il[538]) + , poseidon2_T_61_4(il[539]) + , poseidon2_T_61_5(il[540]) + , poseidon2_T_61_6(il[541]) + , poseidon2_T_61_7(il[542]) + , poseidon2_T_62_4(il[543]) + , poseidon2_T_62_5(il[544]) + , poseidon2_T_62_6(il[545]) + , poseidon2_T_62_7(il[546]) + , poseidon2_T_63_4(il[547]) + , poseidon2_T_63_5(il[548]) + , poseidon2_T_63_6(il[549]) + , poseidon2_T_63_7(il[550]) + , poseidon2_a_0(il[551]) + , poseidon2_a_1(il[552]) + , poseidon2_a_2(il[553]) + , poseidon2_a_3(il[554]) + , poseidon2_b_0(il[555]) + , poseidon2_b_1(il[556]) + , poseidon2_b_2(il[557]) + , poseidon2_b_3(il[558]) + , poseidon2_clk(il[559]) + , poseidon2_input_addr(il[560]) + , poseidon2_mem_addr_read_a(il[561]) + , poseidon2_mem_addr_read_b(il[562]) + , poseidon2_mem_addr_read_c(il[563]) + , poseidon2_mem_addr_read_d(il[564]) + , poseidon2_mem_addr_write_a(il[565]) + , poseidon2_mem_addr_write_b(il[566]) + , poseidon2_mem_addr_write_c(il[567]) + , poseidon2_mem_addr_write_d(il[568]) + , poseidon2_output_addr(il[569]) + , poseidon2_sel_poseidon_perm(il[570]) + , range_check_alu_rng_chk(il[571]) + , range_check_clk(il[572]) + , range_check_cmp_hi_bits_rng_chk(il[573]) + , range_check_cmp_lo_bits_rng_chk(il[574]) + , range_check_dyn_diff(il[575]) + , range_check_dyn_rng_chk_bits(il[576]) + , range_check_dyn_rng_chk_pow_2(il[577]) + , range_check_gas_da_rng_chk(il[578]) + , range_check_gas_l2_rng_chk(il[579]) + , range_check_is_lte_u112(il[580]) + , range_check_is_lte_u128(il[581]) + , range_check_is_lte_u16(il[582]) + , range_check_is_lte_u32(il[583]) + , range_check_is_lte_u48(il[584]) + , range_check_is_lte_u64(il[585]) + , range_check_is_lte_u80(il[586]) + , range_check_is_lte_u96(il[587]) + , range_check_mem_rng_chk(il[588]) + , range_check_rng_chk_bits(il[589]) + , range_check_sel_lookup_0(il[590]) + , range_check_sel_lookup_1(il[591]) + , range_check_sel_lookup_2(il[592]) + , range_check_sel_lookup_3(il[593]) + , range_check_sel_lookup_4(il[594]) + , range_check_sel_lookup_5(il[595]) + , range_check_sel_lookup_6(il[596]) + , range_check_sel_rng_chk(il[597]) + , range_check_u16_r0(il[598]) + , range_check_u16_r1(il[599]) + , range_check_u16_r2(il[600]) + , range_check_u16_r3(il[601]) + , range_check_u16_r4(il[602]) + , range_check_u16_r5(il[603]) + , range_check_u16_r6(il[604]) + , range_check_u16_r7(il[605]) + , range_check_value(il[606]) + , sha256_clk(il[607]) + , sha256_input(il[608]) + , sha256_output(il[609]) + , sha256_sel_sha256_compression(il[610]) + , sha256_state(il[611]) + , slice_addr(il[612]) + , slice_clk(il[613]) + , slice_cnt(il[614]) + , slice_col_offset(il[615]) + , slice_one_min_inv(il[616]) + , slice_sel_cd_cpy(il[617]) + , slice_sel_mem_active(il[618]) + , slice_sel_return(il[619]) + , slice_sel_start(il[620]) + , slice_space_id(il[621]) + , slice_val(il[622]) + , lookup_rng_chk_pow_2_counts(il[623]) + , lookup_rng_chk_diff_counts(il[624]) + , lookup_rng_chk_0_counts(il[625]) + , lookup_rng_chk_1_counts(il[626]) + , lookup_rng_chk_2_counts(il[627]) + , lookup_rng_chk_3_counts(il[628]) + , lookup_rng_chk_4_counts(il[629]) + , lookup_rng_chk_5_counts(il[630]) + , lookup_rng_chk_6_counts(il[631]) + , lookup_rng_chk_7_counts(il[632]) + , lookup_pow_2_0_counts(il[633]) + , lookup_pow_2_1_counts(il[634]) + , lookup_byte_lengths_counts(il[635]) + , lookup_byte_operations_counts(il[636]) + , lookup_opcode_gas_counts(il[637]) + , kernel_output_lookup_counts(il[638]) + , lookup_into_kernel_counts(il[639]) + , lookup_cd_value_counts(il[640]) + , lookup_ret_value_counts(il[641]) + , incl_main_tag_err_counts(il[642]) + , incl_mem_tag_err_counts(il[643]) + , perm_rng_mem_inv(il[644]) + , perm_rng_cmp_lo_inv(il[645]) + , perm_rng_cmp_hi_inv(il[646]) + , perm_rng_alu_inv(il[647]) + , perm_cmp_alu_inv(il[648]) + , perm_rng_gas_l2_inv(il[649]) + , perm_rng_gas_da_inv(il[650]) + , perm_pos_mem_read_a_inv(il[651]) + , perm_pos_mem_read_b_inv(il[652]) + , perm_pos_mem_read_c_inv(il[653]) + , perm_pos_mem_read_d_inv(il[654]) + , perm_pos_mem_write_a_inv(il[655]) + , perm_pos_mem_write_b_inv(il[656]) + , perm_pos_mem_write_c_inv(il[657]) + , perm_pos_mem_write_d_inv(il[658]) + , perm_slice_mem_inv(il[659]) + , perm_main_alu_inv(il[660]) + , perm_main_bin_inv(il[661]) + , perm_main_conv_inv(il[662]) + , perm_main_pos2_perm_inv(il[663]) + , perm_main_pedersen_inv(il[664]) + , perm_main_slice_inv(il[665]) + , perm_main_mem_a_inv(il[666]) + , perm_main_mem_b_inv(il[667]) + , perm_main_mem_c_inv(il[668]) + , perm_main_mem_d_inv(il[669]) + , perm_main_mem_ind_addr_a_inv(il[670]) + , perm_main_mem_ind_addr_b_inv(il[671]) + , perm_main_mem_ind_addr_c_inv(il[672]) + , perm_main_mem_ind_addr_d_inv(il[673]) + , lookup_rng_chk_pow_2_inv(il[674]) + , lookup_rng_chk_diff_inv(il[675]) + , lookup_rng_chk_0_inv(il[676]) + , lookup_rng_chk_1_inv(il[677]) + , lookup_rng_chk_2_inv(il[678]) + , lookup_rng_chk_3_inv(il[679]) + , lookup_rng_chk_4_inv(il[680]) + , lookup_rng_chk_5_inv(il[681]) + , lookup_rng_chk_6_inv(il[682]) + , lookup_rng_chk_7_inv(il[683]) + , lookup_pow_2_0_inv(il[684]) + , lookup_pow_2_1_inv(il[685]) + , lookup_byte_lengths_inv(il[686]) + , lookup_byte_operations_inv(il[687]) + , lookup_opcode_gas_inv(il[688]) + , kernel_output_lookup_inv(il[689]) + , lookup_into_kernel_inv(il[690]) + , lookup_cd_value_inv(il[691]) + , lookup_ret_value_inv(il[692]) + , incl_main_tag_err_inv(il[693]) + , incl_mem_tag_err_inv(il[694]) + , binary_acc_ia_shift(il[695]) + , binary_acc_ib_shift(il[696]) + , binary_acc_ic_shift(il[697]) + , binary_mem_tag_ctr_shift(il[698]) + , binary_op_id_shift(il[699]) + , cmp_a_hi_shift(il[700]) + , cmp_a_lo_shift(il[701]) + , cmp_b_hi_shift(il[702]) + , cmp_b_lo_shift(il[703]) + , cmp_cmp_rng_ctr_shift(il[704]) + , cmp_op_gt_shift(il[705]) + , cmp_p_sub_a_hi_shift(il[706]) + , cmp_p_sub_a_lo_shift(il[707]) + , cmp_p_sub_b_hi_shift(il[708]) + , cmp_p_sub_b_lo_shift(il[709]) + , cmp_sel_rng_chk_shift(il[710]) + , main_da_gas_remaining_shift(il[711]) + , main_emit_l2_to_l1_msg_write_offset_shift(il[712]) + , main_emit_note_hash_write_offset_shift(il[713]) + , main_emit_nullifier_write_offset_shift(il[714]) + , main_emit_unencrypted_log_write_offset_shift(il[715]) + , main_internal_return_ptr_shift(il[716]) + , main_l1_to_l2_msg_exists_write_offset_shift(il[717]) + , main_l2_gas_remaining_shift(il[718]) + , main_note_hash_exist_write_offset_shift(il[719]) + , main_nullifier_exists_write_offset_shift(il[720]) + , main_nullifier_non_exists_write_offset_shift(il[721]) + , main_pc_shift(il[722]) + , main_sel_execution_row_shift(il[723]) + , main_sload_write_offset_shift(il[724]) + , main_sstore_write_offset_shift(il[725]) + , mem_glob_addr_shift(il[726]) + , mem_rw_shift(il[727]) + , mem_sel_mem_shift(il[728]) + , mem_tag_shift(il[729]) + , mem_tsp_shift(il[730]) + , mem_val_shift(il[731]) + , slice_addr_shift(il[732]) + , slice_clk_shift(il[733]) + , slice_cnt_shift(il[734]) + , slice_col_offset_shift(il[735]) + , slice_sel_cd_cpy_shift(il[736]) + , slice_sel_mem_active_shift(il[737]) + , slice_sel_return_shift(il[738]) + , slice_sel_start_shift(il[739]) + , slice_space_id_shift(il[740]) {} AvmFlavor::ProverPolynomials::ProverPolynomials(ProvingKey& proving_key) @@ -947,7 +946,6 @@ AvmFlavor::AllConstRefValues AvmFlavor::ProverPolynomials::get_row(size_t row_id main_sel_op_cast[row_idx], main_sel_op_chain_id[row_idx], main_sel_op_cmov[row_idx], - main_sel_op_coinbase[row_idx], main_sel_op_dagasleft[row_idx], main_sel_op_div[row_idx], main_sel_op_ecadd[row_idx], @@ -1693,7 +1691,6 @@ AvmFlavor::CommitmentLabels::CommitmentLabels() Base::main_sel_op_cast = "MAIN_SEL_OP_CAST"; Base::main_sel_op_chain_id = "MAIN_SEL_OP_CHAIN_ID"; Base::main_sel_op_cmov = "MAIN_SEL_OP_CMOV"; - Base::main_sel_op_coinbase = "MAIN_SEL_OP_COINBASE"; Base::main_sel_op_dagasleft = "MAIN_SEL_OP_DAGASLEFT"; Base::main_sel_op_div = "MAIN_SEL_OP_DIV"; Base::main_sel_op_ecadd = "MAIN_SEL_OP_ECADD"; @@ -2207,6 +2204,10 @@ AvmFlavor::CommitmentLabels::CommitmentLabels() Base::incl_mem_tag_err_counts = "INCL_MEM_TAG_ERR_COUNTS"; }; +// Note: current de-/serialization routines are not including the padded zero univariates which are added as part of +// current sumcheck implementation. Namely, this algorithm is padding to reach CONST_PROOF_SIZE_LOG_N sumcheck rounds. +// Similarly, zeromorph implementation performs same padding over some commitments (zm_cq_comms). +// In code below, the loops are of size log(circuit_size) instead of CONST_PROOF_SIZE_LOG_N. void AvmFlavor::Transcript::deserialize_full_transcript() { size_t num_frs_read = 0; @@ -2229,6 +2230,7 @@ void AvmFlavor::Transcript::deserialize_full_transcript() zm_pi_comm = deserialize_from_buffer(proof_data, num_frs_read); } +// See note above AvmFlavor::Transcript::deserialize_full_transcript() void AvmFlavor::Transcript::serialize_full_transcript() { size_t old_proof_length = proof_data.size(); @@ -2281,4 +2283,20 @@ AvmFlavor::ProvingKey::ProvingKey(const size_t circuit_size, const size_t num_pu } }; +/** + * @brief Serialize verification key to field elements + * + * @return std::vector + */ +std::vector AvmFlavor::VerificationKey::to_field_elements() const +{ + std::vector elements = { FF(circuit_size), FF(num_public_inputs) }; + + for (auto const& comm : get_all()) { + std::vector comm_as_fields = field_conversion::convert_to_bn254_frs(comm); + elements.insert(elements.end(), comm_as_fields.begin(), comm_as_fields.end()); + } + return elements; +} + } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp index 47228fbf667..7d3cabeeca8 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp @@ -89,7 +89,7 @@ template using tuple_cat_t = decltype(std::tuple_cat(std:: // The entities that will be used in the flavor. // clang-format off #define PRECOMPUTED_ENTITIES byte_lookup_sel_bin, byte_lookup_table_byte_lengths, byte_lookup_table_in_tags, byte_lookup_table_input_a, byte_lookup_table_input_b, byte_lookup_table_op_id, byte_lookup_table_output, gas_base_da_gas_fixed_table, gas_base_l2_gas_fixed_table, gas_dyn_da_gas_fixed_table, gas_dyn_l2_gas_fixed_table, gas_sel_gas_cost, main_clk, main_sel_first, main_zeroes, powers_power_of_2 -#define WIRE_ENTITIES main_kernel_inputs, main_kernel_value_out, main_kernel_side_effect_out, main_kernel_metadata_out, main_calldata, main_returndata, alu_a_hi, alu_a_lo, alu_b_hi, alu_b_lo, alu_b_pow, alu_c_hi, alu_c_lo, alu_cf, alu_clk, alu_cmp_gadget_gt, alu_cmp_gadget_input_a, alu_cmp_gadget_input_b, alu_cmp_gadget_result, alu_cmp_gadget_sel, alu_ff_tag, alu_ia, alu_ib, alu_ic, alu_in_tag, alu_max_bits_sub_b_bits, alu_max_bits_sub_b_pow, alu_op_add, alu_op_cast, alu_op_div, alu_op_eq, alu_op_lt, alu_op_lte, alu_op_mul, alu_op_not, alu_op_shl, alu_op_shr, alu_op_sub, alu_partial_prod_hi, alu_partial_prod_lo, alu_range_check_input_value, alu_range_check_num_bits, alu_range_check_sel, alu_remainder, alu_sel_alu, alu_sel_cmp, alu_sel_shift_which, alu_u128_tag, alu_u16_tag, alu_u32_tag, alu_u64_tag, alu_u8_tag, alu_zero_shift, binary_acc_ia, binary_acc_ib, binary_acc_ic, binary_clk, binary_ia_bytes, binary_ib_bytes, binary_ic_bytes, binary_in_tag, binary_mem_tag_ctr, binary_mem_tag_ctr_inv, binary_op_id, binary_sel_bin, binary_start, cmp_a_hi, cmp_a_lo, cmp_b_hi, cmp_b_lo, cmp_borrow, cmp_clk, cmp_cmp_rng_ctr, cmp_input_a, cmp_input_b, cmp_op_eq, cmp_op_eq_diff_inv, cmp_op_gt, cmp_p_a_borrow, cmp_p_b_borrow, cmp_p_sub_a_hi, cmp_p_sub_a_lo, cmp_p_sub_b_hi, cmp_p_sub_b_lo, cmp_range_chk_clk, cmp_res_hi, cmp_res_lo, cmp_result, cmp_sel_cmp, cmp_sel_rng_chk, cmp_shift_sel, conversion_clk, conversion_input, conversion_num_limbs, conversion_radix, conversion_sel_to_radix_le, keccakf1600_clk, keccakf1600_input, keccakf1600_output, keccakf1600_sel_keccakf1600, main_abs_da_rem_gas, main_abs_l2_rem_gas, main_alu_in_tag, main_base_da_gas_op_cost, main_base_l2_gas_op_cost, main_bin_op_id, main_call_ptr, main_da_gas_remaining, main_da_out_of_gas, main_dyn_da_gas_op_cost, main_dyn_gas_multiplier, main_dyn_l2_gas_op_cost, main_emit_l2_to_l1_msg_write_offset, main_emit_note_hash_write_offset, main_emit_nullifier_write_offset, main_emit_unencrypted_log_write_offset, main_ia, main_ib, main_ic, main_id, main_id_zero, main_ind_addr_a, main_ind_addr_b, main_ind_addr_c, main_ind_addr_d, main_internal_return_ptr, main_inv, main_kernel_in_offset, main_kernel_out_offset, main_l1_to_l2_msg_exists_write_offset, main_l2_gas_remaining, main_l2_out_of_gas, main_mem_addr_a, main_mem_addr_b, main_mem_addr_c, main_mem_addr_d, main_note_hash_exist_write_offset, main_nullifier_exists_write_offset, main_nullifier_non_exists_write_offset, main_op_err, main_opcode_val, main_pc, main_r_in_tag, main_rwa, main_rwb, main_rwc, main_rwd, main_sel_alu, main_sel_bin, main_sel_calldata, main_sel_execution_row, main_sel_kernel_inputs, main_sel_kernel_out, main_sel_last, main_sel_mem_op_a, main_sel_mem_op_b, main_sel_mem_op_c, main_sel_mem_op_d, main_sel_mov_ia_to_ic, main_sel_mov_ib_to_ic, main_sel_op_add, main_sel_op_address, main_sel_op_and, main_sel_op_block_number, main_sel_op_calldata_copy, main_sel_op_cast, main_sel_op_chain_id, main_sel_op_cmov, main_sel_op_coinbase, main_sel_op_dagasleft, main_sel_op_div, main_sel_op_ecadd, main_sel_op_emit_l2_to_l1_msg, main_sel_op_emit_note_hash, main_sel_op_emit_nullifier, main_sel_op_emit_unencrypted_log, main_sel_op_eq, main_sel_op_external_call, main_sel_op_external_return, main_sel_op_external_revert, main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_internal_call, main_sel_op_internal_return, main_sel_op_jump, main_sel_op_jumpi, main_sel_op_keccak, main_sel_op_l1_to_l2_msg_exists, main_sel_op_l2gasleft, main_sel_op_lt, main_sel_op_lte, main_sel_op_mov, main_sel_op_msm, main_sel_op_mul, main_sel_op_not, main_sel_op_note_hash_exists, main_sel_op_nullifier_exists, main_sel_op_or, main_sel_op_pedersen, main_sel_op_pedersen_commit, main_sel_op_poseidon2, main_sel_op_radix_le, main_sel_op_sender, main_sel_op_set, main_sel_op_sha256, main_sel_op_shl, main_sel_op_shr, main_sel_op_sload, main_sel_op_sstore, main_sel_op_storage_address, main_sel_op_sub, main_sel_op_timestamp, main_sel_op_transaction_fee, main_sel_op_version, main_sel_op_xor, main_sel_q_kernel_lookup, main_sel_q_kernel_output_lookup, main_sel_resolve_ind_addr_a, main_sel_resolve_ind_addr_b, main_sel_resolve_ind_addr_c, main_sel_resolve_ind_addr_d, main_sel_returndata, main_sel_rng_16, main_sel_rng_8, main_sel_slice_gadget, main_side_effect_counter, main_sload_write_offset, main_space_id, main_sstore_write_offset, main_tag_err, main_w_in_tag, mem_addr, mem_clk, mem_diff, mem_glob_addr, mem_last, mem_lastAccess, mem_one_min_inv, mem_r_in_tag, mem_rw, mem_sel_mem, mem_sel_mov_ia_to_ic, mem_sel_mov_ib_to_ic, mem_sel_op_a, mem_sel_op_b, mem_sel_op_c, mem_sel_op_cmov, mem_sel_op_d, mem_sel_op_poseidon_read_a, mem_sel_op_poseidon_read_b, mem_sel_op_poseidon_read_c, mem_sel_op_poseidon_read_d, mem_sel_op_poseidon_write_a, mem_sel_op_poseidon_write_b, mem_sel_op_poseidon_write_c, mem_sel_op_poseidon_write_d, mem_sel_op_slice, mem_sel_resolve_ind_addr_a, mem_sel_resolve_ind_addr_b, mem_sel_resolve_ind_addr_c, mem_sel_resolve_ind_addr_d, mem_sel_rng_chk, mem_skip_check_tag, mem_space_id, mem_tag, mem_tag_err, mem_tsp, mem_val, mem_w_in_tag, pedersen_clk, pedersen_input, pedersen_output, pedersen_sel_pedersen, poseidon2_B_10_0, poseidon2_B_10_1, poseidon2_B_10_2, poseidon2_B_10_3, poseidon2_B_11_0, poseidon2_B_11_1, poseidon2_B_11_2, poseidon2_B_11_3, poseidon2_B_12_0, poseidon2_B_12_1, poseidon2_B_12_2, poseidon2_B_12_3, poseidon2_B_13_0, poseidon2_B_13_1, poseidon2_B_13_2, poseidon2_B_13_3, poseidon2_B_14_0, poseidon2_B_14_1, poseidon2_B_14_2, poseidon2_B_14_3, poseidon2_B_15_0, poseidon2_B_15_1, poseidon2_B_15_2, poseidon2_B_15_3, poseidon2_B_16_0, poseidon2_B_16_1, poseidon2_B_16_2, poseidon2_B_16_3, poseidon2_B_17_0, poseidon2_B_17_1, poseidon2_B_17_2, poseidon2_B_17_3, poseidon2_B_18_0, poseidon2_B_18_1, poseidon2_B_18_2, poseidon2_B_18_3, poseidon2_B_19_0, poseidon2_B_19_1, poseidon2_B_19_2, poseidon2_B_19_3, poseidon2_B_20_0, poseidon2_B_20_1, poseidon2_B_20_2, poseidon2_B_20_3, poseidon2_B_21_0, poseidon2_B_21_1, poseidon2_B_21_2, poseidon2_B_21_3, poseidon2_B_22_0, poseidon2_B_22_1, poseidon2_B_22_2, poseidon2_B_22_3, poseidon2_B_23_0, poseidon2_B_23_1, poseidon2_B_23_2, poseidon2_B_23_3, poseidon2_B_24_0, poseidon2_B_24_1, poseidon2_B_24_2, poseidon2_B_24_3, poseidon2_B_25_0, poseidon2_B_25_1, poseidon2_B_25_2, poseidon2_B_25_3, poseidon2_B_26_0, poseidon2_B_26_1, poseidon2_B_26_2, poseidon2_B_26_3, poseidon2_B_27_0, poseidon2_B_27_1, poseidon2_B_27_2, poseidon2_B_27_3, poseidon2_B_28_0, poseidon2_B_28_1, poseidon2_B_28_2, poseidon2_B_28_3, poseidon2_B_29_0, poseidon2_B_29_1, poseidon2_B_29_2, poseidon2_B_29_3, poseidon2_B_30_0, poseidon2_B_30_1, poseidon2_B_30_2, poseidon2_B_30_3, poseidon2_B_31_0, poseidon2_B_31_1, poseidon2_B_31_2, poseidon2_B_31_3, poseidon2_B_32_0, poseidon2_B_32_1, poseidon2_B_32_2, poseidon2_B_32_3, poseidon2_B_33_0, poseidon2_B_33_1, poseidon2_B_33_2, poseidon2_B_33_3, poseidon2_B_34_0, poseidon2_B_34_1, poseidon2_B_34_2, poseidon2_B_34_3, poseidon2_B_35_0, poseidon2_B_35_1, poseidon2_B_35_2, poseidon2_B_35_3, poseidon2_B_36_0, poseidon2_B_36_1, poseidon2_B_36_2, poseidon2_B_36_3, poseidon2_B_37_0, poseidon2_B_37_1, poseidon2_B_37_2, poseidon2_B_37_3, poseidon2_B_38_0, poseidon2_B_38_1, poseidon2_B_38_2, poseidon2_B_38_3, poseidon2_B_39_0, poseidon2_B_39_1, poseidon2_B_39_2, poseidon2_B_39_3, poseidon2_B_40_0, poseidon2_B_40_1, poseidon2_B_40_2, poseidon2_B_40_3, poseidon2_B_41_0, poseidon2_B_41_1, poseidon2_B_41_2, poseidon2_B_41_3, poseidon2_B_42_0, poseidon2_B_42_1, poseidon2_B_42_2, poseidon2_B_42_3, poseidon2_B_43_0, poseidon2_B_43_1, poseidon2_B_43_2, poseidon2_B_43_3, poseidon2_B_44_0, poseidon2_B_44_1, poseidon2_B_44_2, poseidon2_B_44_3, poseidon2_B_45_0, poseidon2_B_45_1, poseidon2_B_45_2, poseidon2_B_45_3, poseidon2_B_46_0, poseidon2_B_46_1, poseidon2_B_46_2, poseidon2_B_46_3, poseidon2_B_47_0, poseidon2_B_47_1, poseidon2_B_47_2, poseidon2_B_47_3, poseidon2_B_48_0, poseidon2_B_48_1, poseidon2_B_48_2, poseidon2_B_48_3, poseidon2_B_49_0, poseidon2_B_49_1, poseidon2_B_49_2, poseidon2_B_49_3, poseidon2_B_4_0, poseidon2_B_4_1, poseidon2_B_4_2, poseidon2_B_4_3, poseidon2_B_50_0, poseidon2_B_50_1, poseidon2_B_50_2, poseidon2_B_50_3, poseidon2_B_51_0, poseidon2_B_51_1, poseidon2_B_51_2, poseidon2_B_51_3, poseidon2_B_52_0, poseidon2_B_52_1, poseidon2_B_52_2, poseidon2_B_52_3, poseidon2_B_53_0, poseidon2_B_53_1, poseidon2_B_53_2, poseidon2_B_53_3, poseidon2_B_54_0, poseidon2_B_54_1, poseidon2_B_54_2, poseidon2_B_54_3, poseidon2_B_55_0, poseidon2_B_55_1, poseidon2_B_55_2, poseidon2_B_55_3, poseidon2_B_56_0, poseidon2_B_56_1, poseidon2_B_56_2, poseidon2_B_56_3, poseidon2_B_57_0, poseidon2_B_57_1, poseidon2_B_57_2, poseidon2_B_57_3, poseidon2_B_58_0, poseidon2_B_58_1, poseidon2_B_58_2, poseidon2_B_58_3, poseidon2_B_59_0, poseidon2_B_59_1, poseidon2_B_59_2, poseidon2_B_59_3, poseidon2_B_5_0, poseidon2_B_5_1, poseidon2_B_5_2, poseidon2_B_5_3, poseidon2_B_6_0, poseidon2_B_6_1, poseidon2_B_6_2, poseidon2_B_6_3, poseidon2_B_7_0, poseidon2_B_7_1, poseidon2_B_7_2, poseidon2_B_7_3, poseidon2_B_8_0, poseidon2_B_8_1, poseidon2_B_8_2, poseidon2_B_8_3, poseidon2_B_9_0, poseidon2_B_9_1, poseidon2_B_9_2, poseidon2_B_9_3, poseidon2_EXT_LAYER_4, poseidon2_EXT_LAYER_5, poseidon2_EXT_LAYER_6, poseidon2_EXT_LAYER_7, poseidon2_T_0_4, poseidon2_T_0_5, poseidon2_T_0_6, poseidon2_T_0_7, poseidon2_T_1_4, poseidon2_T_1_5, poseidon2_T_1_6, poseidon2_T_1_7, poseidon2_T_2_4, poseidon2_T_2_5, poseidon2_T_2_6, poseidon2_T_2_7, poseidon2_T_3_4, poseidon2_T_3_5, poseidon2_T_3_6, poseidon2_T_3_7, poseidon2_T_60_4, poseidon2_T_60_5, poseidon2_T_60_6, poseidon2_T_60_7, poseidon2_T_61_4, poseidon2_T_61_5, poseidon2_T_61_6, poseidon2_T_61_7, poseidon2_T_62_4, poseidon2_T_62_5, poseidon2_T_62_6, poseidon2_T_62_7, poseidon2_T_63_4, poseidon2_T_63_5, poseidon2_T_63_6, poseidon2_T_63_7, poseidon2_a_0, poseidon2_a_1, poseidon2_a_2, poseidon2_a_3, poseidon2_b_0, poseidon2_b_1, poseidon2_b_2, poseidon2_b_3, poseidon2_clk, poseidon2_input_addr, poseidon2_mem_addr_read_a, poseidon2_mem_addr_read_b, poseidon2_mem_addr_read_c, poseidon2_mem_addr_read_d, poseidon2_mem_addr_write_a, poseidon2_mem_addr_write_b, poseidon2_mem_addr_write_c, poseidon2_mem_addr_write_d, poseidon2_output_addr, poseidon2_sel_poseidon_perm, range_check_alu_rng_chk, range_check_clk, range_check_cmp_hi_bits_rng_chk, range_check_cmp_lo_bits_rng_chk, range_check_dyn_diff, range_check_dyn_rng_chk_bits, range_check_dyn_rng_chk_pow_2, range_check_gas_da_rng_chk, range_check_gas_l2_rng_chk, range_check_is_lte_u112, range_check_is_lte_u128, range_check_is_lte_u16, range_check_is_lte_u32, range_check_is_lte_u48, range_check_is_lte_u64, range_check_is_lte_u80, range_check_is_lte_u96, range_check_mem_rng_chk, range_check_rng_chk_bits, range_check_sel_lookup_0, range_check_sel_lookup_1, range_check_sel_lookup_2, range_check_sel_lookup_3, range_check_sel_lookup_4, range_check_sel_lookup_5, range_check_sel_lookup_6, range_check_sel_rng_chk, range_check_u16_r0, range_check_u16_r1, range_check_u16_r2, range_check_u16_r3, range_check_u16_r4, range_check_u16_r5, range_check_u16_r6, range_check_u16_r7, range_check_value, sha256_clk, sha256_input, sha256_output, sha256_sel_sha256_compression, sha256_state, slice_addr, slice_clk, slice_cnt, slice_col_offset, slice_one_min_inv, slice_sel_cd_cpy, slice_sel_mem_active, slice_sel_return, slice_sel_start, slice_space_id, slice_val, lookup_rng_chk_pow_2_counts, lookup_rng_chk_diff_counts, lookup_rng_chk_0_counts, lookup_rng_chk_1_counts, lookup_rng_chk_2_counts, lookup_rng_chk_3_counts, lookup_rng_chk_4_counts, lookup_rng_chk_5_counts, lookup_rng_chk_6_counts, lookup_rng_chk_7_counts, lookup_pow_2_0_counts, lookup_pow_2_1_counts, lookup_byte_lengths_counts, lookup_byte_operations_counts, lookup_opcode_gas_counts, kernel_output_lookup_counts, lookup_into_kernel_counts, lookup_cd_value_counts, lookup_ret_value_counts, incl_main_tag_err_counts, incl_mem_tag_err_counts +#define WIRE_ENTITIES main_kernel_inputs, main_kernel_value_out, main_kernel_side_effect_out, main_kernel_metadata_out, main_calldata, main_returndata, alu_a_hi, alu_a_lo, alu_b_hi, alu_b_lo, alu_b_pow, alu_c_hi, alu_c_lo, alu_cf, alu_clk, alu_cmp_gadget_gt, alu_cmp_gadget_input_a, alu_cmp_gadget_input_b, alu_cmp_gadget_result, alu_cmp_gadget_sel, alu_ff_tag, alu_ia, alu_ib, alu_ic, alu_in_tag, alu_max_bits_sub_b_bits, alu_max_bits_sub_b_pow, alu_op_add, alu_op_cast, alu_op_div, alu_op_eq, alu_op_lt, alu_op_lte, alu_op_mul, alu_op_not, alu_op_shl, alu_op_shr, alu_op_sub, alu_partial_prod_hi, alu_partial_prod_lo, alu_range_check_input_value, alu_range_check_num_bits, alu_range_check_sel, alu_remainder, alu_sel_alu, alu_sel_cmp, alu_sel_shift_which, alu_u128_tag, alu_u16_tag, alu_u32_tag, alu_u64_tag, alu_u8_tag, alu_zero_shift, binary_acc_ia, binary_acc_ib, binary_acc_ic, binary_clk, binary_ia_bytes, binary_ib_bytes, binary_ic_bytes, binary_in_tag, binary_mem_tag_ctr, binary_mem_tag_ctr_inv, binary_op_id, binary_sel_bin, binary_start, cmp_a_hi, cmp_a_lo, cmp_b_hi, cmp_b_lo, cmp_borrow, cmp_clk, cmp_cmp_rng_ctr, cmp_input_a, cmp_input_b, cmp_op_eq, cmp_op_eq_diff_inv, cmp_op_gt, cmp_p_a_borrow, cmp_p_b_borrow, cmp_p_sub_a_hi, cmp_p_sub_a_lo, cmp_p_sub_b_hi, cmp_p_sub_b_lo, cmp_range_chk_clk, cmp_res_hi, cmp_res_lo, cmp_result, cmp_sel_cmp, cmp_sel_rng_chk, cmp_shift_sel, conversion_clk, conversion_input, conversion_num_limbs, conversion_radix, conversion_sel_to_radix_le, keccakf1600_clk, keccakf1600_input, keccakf1600_output, keccakf1600_sel_keccakf1600, main_abs_da_rem_gas, main_abs_l2_rem_gas, main_alu_in_tag, main_base_da_gas_op_cost, main_base_l2_gas_op_cost, main_bin_op_id, main_call_ptr, main_da_gas_remaining, main_da_out_of_gas, main_dyn_da_gas_op_cost, main_dyn_gas_multiplier, main_dyn_l2_gas_op_cost, main_emit_l2_to_l1_msg_write_offset, main_emit_note_hash_write_offset, main_emit_nullifier_write_offset, main_emit_unencrypted_log_write_offset, main_ia, main_ib, main_ic, main_id, main_id_zero, main_ind_addr_a, main_ind_addr_b, main_ind_addr_c, main_ind_addr_d, main_internal_return_ptr, main_inv, main_kernel_in_offset, main_kernel_out_offset, main_l1_to_l2_msg_exists_write_offset, main_l2_gas_remaining, main_l2_out_of_gas, main_mem_addr_a, main_mem_addr_b, main_mem_addr_c, main_mem_addr_d, main_note_hash_exist_write_offset, main_nullifier_exists_write_offset, main_nullifier_non_exists_write_offset, main_op_err, main_opcode_val, main_pc, main_r_in_tag, main_rwa, main_rwb, main_rwc, main_rwd, main_sel_alu, main_sel_bin, main_sel_calldata, main_sel_execution_row, main_sel_kernel_inputs, main_sel_kernel_out, main_sel_last, main_sel_mem_op_a, main_sel_mem_op_b, main_sel_mem_op_c, main_sel_mem_op_d, main_sel_mov_ia_to_ic, main_sel_mov_ib_to_ic, main_sel_op_add, main_sel_op_address, main_sel_op_and, main_sel_op_block_number, main_sel_op_calldata_copy, main_sel_op_cast, main_sel_op_chain_id, main_sel_op_cmov, main_sel_op_dagasleft, main_sel_op_div, main_sel_op_ecadd, main_sel_op_emit_l2_to_l1_msg, main_sel_op_emit_note_hash, main_sel_op_emit_nullifier, main_sel_op_emit_unencrypted_log, main_sel_op_eq, main_sel_op_external_call, main_sel_op_external_return, main_sel_op_external_revert, main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_internal_call, main_sel_op_internal_return, main_sel_op_jump, main_sel_op_jumpi, main_sel_op_keccak, main_sel_op_l1_to_l2_msg_exists, main_sel_op_l2gasleft, main_sel_op_lt, main_sel_op_lte, main_sel_op_mov, main_sel_op_msm, main_sel_op_mul, main_sel_op_not, main_sel_op_note_hash_exists, main_sel_op_nullifier_exists, main_sel_op_or, main_sel_op_pedersen, main_sel_op_pedersen_commit, main_sel_op_poseidon2, main_sel_op_radix_le, main_sel_op_sender, main_sel_op_set, main_sel_op_sha256, main_sel_op_shl, main_sel_op_shr, main_sel_op_sload, main_sel_op_sstore, main_sel_op_storage_address, main_sel_op_sub, main_sel_op_timestamp, main_sel_op_transaction_fee, main_sel_op_version, main_sel_op_xor, main_sel_q_kernel_lookup, main_sel_q_kernel_output_lookup, main_sel_resolve_ind_addr_a, main_sel_resolve_ind_addr_b, main_sel_resolve_ind_addr_c, main_sel_resolve_ind_addr_d, main_sel_returndata, main_sel_rng_16, main_sel_rng_8, main_sel_slice_gadget, main_side_effect_counter, main_sload_write_offset, main_space_id, main_sstore_write_offset, main_tag_err, main_w_in_tag, mem_addr, mem_clk, mem_diff, mem_glob_addr, mem_last, mem_lastAccess, mem_one_min_inv, mem_r_in_tag, mem_rw, mem_sel_mem, mem_sel_mov_ia_to_ic, mem_sel_mov_ib_to_ic, mem_sel_op_a, mem_sel_op_b, mem_sel_op_c, mem_sel_op_cmov, mem_sel_op_d, mem_sel_op_poseidon_read_a, mem_sel_op_poseidon_read_b, mem_sel_op_poseidon_read_c, mem_sel_op_poseidon_read_d, mem_sel_op_poseidon_write_a, mem_sel_op_poseidon_write_b, mem_sel_op_poseidon_write_c, mem_sel_op_poseidon_write_d, mem_sel_op_slice, mem_sel_resolve_ind_addr_a, mem_sel_resolve_ind_addr_b, mem_sel_resolve_ind_addr_c, mem_sel_resolve_ind_addr_d, mem_sel_rng_chk, mem_skip_check_tag, mem_space_id, mem_tag, mem_tag_err, mem_tsp, mem_val, mem_w_in_tag, pedersen_clk, pedersen_input, pedersen_output, pedersen_sel_pedersen, poseidon2_B_10_0, poseidon2_B_10_1, poseidon2_B_10_2, poseidon2_B_10_3, poseidon2_B_11_0, poseidon2_B_11_1, poseidon2_B_11_2, poseidon2_B_11_3, poseidon2_B_12_0, poseidon2_B_12_1, poseidon2_B_12_2, poseidon2_B_12_3, poseidon2_B_13_0, poseidon2_B_13_1, poseidon2_B_13_2, poseidon2_B_13_3, poseidon2_B_14_0, poseidon2_B_14_1, poseidon2_B_14_2, poseidon2_B_14_3, poseidon2_B_15_0, poseidon2_B_15_1, poseidon2_B_15_2, poseidon2_B_15_3, poseidon2_B_16_0, poseidon2_B_16_1, poseidon2_B_16_2, poseidon2_B_16_3, poseidon2_B_17_0, poseidon2_B_17_1, poseidon2_B_17_2, poseidon2_B_17_3, poseidon2_B_18_0, poseidon2_B_18_1, poseidon2_B_18_2, poseidon2_B_18_3, poseidon2_B_19_0, poseidon2_B_19_1, poseidon2_B_19_2, poseidon2_B_19_3, poseidon2_B_20_0, poseidon2_B_20_1, poseidon2_B_20_2, poseidon2_B_20_3, poseidon2_B_21_0, poseidon2_B_21_1, poseidon2_B_21_2, poseidon2_B_21_3, poseidon2_B_22_0, poseidon2_B_22_1, poseidon2_B_22_2, poseidon2_B_22_3, poseidon2_B_23_0, poseidon2_B_23_1, poseidon2_B_23_2, poseidon2_B_23_3, poseidon2_B_24_0, poseidon2_B_24_1, poseidon2_B_24_2, poseidon2_B_24_3, poseidon2_B_25_0, poseidon2_B_25_1, poseidon2_B_25_2, poseidon2_B_25_3, poseidon2_B_26_0, poseidon2_B_26_1, poseidon2_B_26_2, poseidon2_B_26_3, poseidon2_B_27_0, poseidon2_B_27_1, poseidon2_B_27_2, poseidon2_B_27_3, poseidon2_B_28_0, poseidon2_B_28_1, poseidon2_B_28_2, poseidon2_B_28_3, poseidon2_B_29_0, poseidon2_B_29_1, poseidon2_B_29_2, poseidon2_B_29_3, poseidon2_B_30_0, poseidon2_B_30_1, poseidon2_B_30_2, poseidon2_B_30_3, poseidon2_B_31_0, poseidon2_B_31_1, poseidon2_B_31_2, poseidon2_B_31_3, poseidon2_B_32_0, poseidon2_B_32_1, poseidon2_B_32_2, poseidon2_B_32_3, poseidon2_B_33_0, poseidon2_B_33_1, poseidon2_B_33_2, poseidon2_B_33_3, poseidon2_B_34_0, poseidon2_B_34_1, poseidon2_B_34_2, poseidon2_B_34_3, poseidon2_B_35_0, poseidon2_B_35_1, poseidon2_B_35_2, poseidon2_B_35_3, poseidon2_B_36_0, poseidon2_B_36_1, poseidon2_B_36_2, poseidon2_B_36_3, poseidon2_B_37_0, poseidon2_B_37_1, poseidon2_B_37_2, poseidon2_B_37_3, poseidon2_B_38_0, poseidon2_B_38_1, poseidon2_B_38_2, poseidon2_B_38_3, poseidon2_B_39_0, poseidon2_B_39_1, poseidon2_B_39_2, poseidon2_B_39_3, poseidon2_B_40_0, poseidon2_B_40_1, poseidon2_B_40_2, poseidon2_B_40_3, poseidon2_B_41_0, poseidon2_B_41_1, poseidon2_B_41_2, poseidon2_B_41_3, poseidon2_B_42_0, poseidon2_B_42_1, poseidon2_B_42_2, poseidon2_B_42_3, poseidon2_B_43_0, poseidon2_B_43_1, poseidon2_B_43_2, poseidon2_B_43_3, poseidon2_B_44_0, poseidon2_B_44_1, poseidon2_B_44_2, poseidon2_B_44_3, poseidon2_B_45_0, poseidon2_B_45_1, poseidon2_B_45_2, poseidon2_B_45_3, poseidon2_B_46_0, poseidon2_B_46_1, poseidon2_B_46_2, poseidon2_B_46_3, poseidon2_B_47_0, poseidon2_B_47_1, poseidon2_B_47_2, poseidon2_B_47_3, poseidon2_B_48_0, poseidon2_B_48_1, poseidon2_B_48_2, poseidon2_B_48_3, poseidon2_B_49_0, poseidon2_B_49_1, poseidon2_B_49_2, poseidon2_B_49_3, poseidon2_B_4_0, poseidon2_B_4_1, poseidon2_B_4_2, poseidon2_B_4_3, poseidon2_B_50_0, poseidon2_B_50_1, poseidon2_B_50_2, poseidon2_B_50_3, poseidon2_B_51_0, poseidon2_B_51_1, poseidon2_B_51_2, poseidon2_B_51_3, poseidon2_B_52_0, poseidon2_B_52_1, poseidon2_B_52_2, poseidon2_B_52_3, poseidon2_B_53_0, poseidon2_B_53_1, poseidon2_B_53_2, poseidon2_B_53_3, poseidon2_B_54_0, poseidon2_B_54_1, poseidon2_B_54_2, poseidon2_B_54_3, poseidon2_B_55_0, poseidon2_B_55_1, poseidon2_B_55_2, poseidon2_B_55_3, poseidon2_B_56_0, poseidon2_B_56_1, poseidon2_B_56_2, poseidon2_B_56_3, poseidon2_B_57_0, poseidon2_B_57_1, poseidon2_B_57_2, poseidon2_B_57_3, poseidon2_B_58_0, poseidon2_B_58_1, poseidon2_B_58_2, poseidon2_B_58_3, poseidon2_B_59_0, poseidon2_B_59_1, poseidon2_B_59_2, poseidon2_B_59_3, poseidon2_B_5_0, poseidon2_B_5_1, poseidon2_B_5_2, poseidon2_B_5_3, poseidon2_B_6_0, poseidon2_B_6_1, poseidon2_B_6_2, poseidon2_B_6_3, poseidon2_B_7_0, poseidon2_B_7_1, poseidon2_B_7_2, poseidon2_B_7_3, poseidon2_B_8_0, poseidon2_B_8_1, poseidon2_B_8_2, poseidon2_B_8_3, poseidon2_B_9_0, poseidon2_B_9_1, poseidon2_B_9_2, poseidon2_B_9_3, poseidon2_EXT_LAYER_4, poseidon2_EXT_LAYER_5, poseidon2_EXT_LAYER_6, poseidon2_EXT_LAYER_7, poseidon2_T_0_4, poseidon2_T_0_5, poseidon2_T_0_6, poseidon2_T_0_7, poseidon2_T_1_4, poseidon2_T_1_5, poseidon2_T_1_6, poseidon2_T_1_7, poseidon2_T_2_4, poseidon2_T_2_5, poseidon2_T_2_6, poseidon2_T_2_7, poseidon2_T_3_4, poseidon2_T_3_5, poseidon2_T_3_6, poseidon2_T_3_7, poseidon2_T_60_4, poseidon2_T_60_5, poseidon2_T_60_6, poseidon2_T_60_7, poseidon2_T_61_4, poseidon2_T_61_5, poseidon2_T_61_6, poseidon2_T_61_7, poseidon2_T_62_4, poseidon2_T_62_5, poseidon2_T_62_6, poseidon2_T_62_7, poseidon2_T_63_4, poseidon2_T_63_5, poseidon2_T_63_6, poseidon2_T_63_7, poseidon2_a_0, poseidon2_a_1, poseidon2_a_2, poseidon2_a_3, poseidon2_b_0, poseidon2_b_1, poseidon2_b_2, poseidon2_b_3, poseidon2_clk, poseidon2_input_addr, poseidon2_mem_addr_read_a, poseidon2_mem_addr_read_b, poseidon2_mem_addr_read_c, poseidon2_mem_addr_read_d, poseidon2_mem_addr_write_a, poseidon2_mem_addr_write_b, poseidon2_mem_addr_write_c, poseidon2_mem_addr_write_d, poseidon2_output_addr, poseidon2_sel_poseidon_perm, range_check_alu_rng_chk, range_check_clk, range_check_cmp_hi_bits_rng_chk, range_check_cmp_lo_bits_rng_chk, range_check_dyn_diff, range_check_dyn_rng_chk_bits, range_check_dyn_rng_chk_pow_2, range_check_gas_da_rng_chk, range_check_gas_l2_rng_chk, range_check_is_lte_u112, range_check_is_lte_u128, range_check_is_lte_u16, range_check_is_lte_u32, range_check_is_lte_u48, range_check_is_lte_u64, range_check_is_lte_u80, range_check_is_lte_u96, range_check_mem_rng_chk, range_check_rng_chk_bits, range_check_sel_lookup_0, range_check_sel_lookup_1, range_check_sel_lookup_2, range_check_sel_lookup_3, range_check_sel_lookup_4, range_check_sel_lookup_5, range_check_sel_lookup_6, range_check_sel_rng_chk, range_check_u16_r0, range_check_u16_r1, range_check_u16_r2, range_check_u16_r3, range_check_u16_r4, range_check_u16_r5, range_check_u16_r6, range_check_u16_r7, range_check_value, sha256_clk, sha256_input, sha256_output, sha256_sel_sha256_compression, sha256_state, slice_addr, slice_clk, slice_cnt, slice_col_offset, slice_one_min_inv, slice_sel_cd_cpy, slice_sel_mem_active, slice_sel_return, slice_sel_start, slice_space_id, slice_val, lookup_rng_chk_pow_2_counts, lookup_rng_chk_diff_counts, lookup_rng_chk_0_counts, lookup_rng_chk_1_counts, lookup_rng_chk_2_counts, lookup_rng_chk_3_counts, lookup_rng_chk_4_counts, lookup_rng_chk_5_counts, lookup_rng_chk_6_counts, lookup_rng_chk_7_counts, lookup_pow_2_0_counts, lookup_pow_2_1_counts, lookup_byte_lengths_counts, lookup_byte_operations_counts, lookup_opcode_gas_counts, kernel_output_lookup_counts, lookup_into_kernel_counts, lookup_cd_value_counts, lookup_ret_value_counts, incl_main_tag_err_counts, incl_mem_tag_err_counts #define DERIVED_WITNESS_ENTITIES perm_rng_mem_inv, perm_rng_cmp_lo_inv, perm_rng_cmp_hi_inv, perm_rng_alu_inv, perm_cmp_alu_inv, perm_rng_gas_l2_inv, perm_rng_gas_da_inv, perm_pos_mem_read_a_inv, perm_pos_mem_read_b_inv, perm_pos_mem_read_c_inv, perm_pos_mem_read_d_inv, perm_pos_mem_write_a_inv, perm_pos_mem_write_b_inv, perm_pos_mem_write_c_inv, perm_pos_mem_write_d_inv, perm_slice_mem_inv, perm_main_alu_inv, perm_main_bin_inv, perm_main_conv_inv, perm_main_pos2_perm_inv, perm_main_pedersen_inv, perm_main_slice_inv, perm_main_mem_a_inv, perm_main_mem_b_inv, perm_main_mem_c_inv, perm_main_mem_d_inv, perm_main_mem_ind_addr_a_inv, perm_main_mem_ind_addr_b_inv, perm_main_mem_ind_addr_c_inv, perm_main_mem_ind_addr_d_inv, lookup_rng_chk_pow_2_inv, lookup_rng_chk_diff_inv, lookup_rng_chk_0_inv, lookup_rng_chk_1_inv, lookup_rng_chk_2_inv, lookup_rng_chk_3_inv, lookup_rng_chk_4_inv, lookup_rng_chk_5_inv, lookup_rng_chk_6_inv, lookup_rng_chk_7_inv, lookup_pow_2_0_inv, lookup_pow_2_1_inv, lookup_byte_lengths_inv, lookup_byte_operations_inv, lookup_opcode_gas_inv, kernel_output_lookup_inv, lookup_into_kernel_inv, lookup_cd_value_inv, lookup_ret_value_inv, incl_main_tag_err_inv, incl_mem_tag_err_inv #define SHIFTED_ENTITIES binary_acc_ia_shift, binary_acc_ib_shift, binary_acc_ic_shift, binary_mem_tag_ctr_shift, binary_op_id_shift, cmp_a_hi_shift, cmp_a_lo_shift, cmp_b_hi_shift, cmp_b_lo_shift, cmp_cmp_rng_ctr_shift, cmp_op_gt_shift, cmp_p_sub_a_hi_shift, cmp_p_sub_a_lo_shift, cmp_p_sub_b_hi_shift, cmp_p_sub_b_lo_shift, cmp_sel_rng_chk_shift, main_da_gas_remaining_shift, main_emit_l2_to_l1_msg_write_offset_shift, main_emit_note_hash_write_offset_shift, main_emit_nullifier_write_offset_shift, main_emit_unencrypted_log_write_offset_shift, main_internal_return_ptr_shift, main_l1_to_l2_msg_exists_write_offset_shift, main_l2_gas_remaining_shift, main_note_hash_exist_write_offset_shift, main_nullifier_exists_write_offset_shift, main_nullifier_non_exists_write_offset_shift, main_pc_shift, main_sel_execution_row_shift, main_sload_write_offset_shift, main_sstore_write_offset_shift, mem_glob_addr_shift, mem_rw_shift, mem_sel_mem_shift, mem_tag_shift, mem_tsp_shift, mem_val_shift, slice_addr_shift, slice_clk_shift, slice_cnt_shift, slice_col_offset_shift, slice_sel_cd_cpy_shift, slice_sel_mem_active_shift, slice_sel_return_shift, slice_sel_start_shift, slice_space_id_shift #define TO_BE_SHIFTED(e) e.binary_acc_ia, e.binary_acc_ib, e.binary_acc_ic, e.binary_mem_tag_ctr, e.binary_op_id, e.cmp_a_hi, e.cmp_a_lo, e.cmp_b_hi, e.cmp_b_lo, e.cmp_cmp_rng_ctr, e.cmp_op_gt, e.cmp_p_sub_a_hi, e.cmp_p_sub_a_lo, e.cmp_p_sub_b_hi, e.cmp_p_sub_b_lo, e.cmp_sel_rng_chk, e.main_da_gas_remaining, e.main_emit_l2_to_l1_msg_write_offset, e.main_emit_note_hash_write_offset, e.main_emit_nullifier_write_offset, e.main_emit_unencrypted_log_write_offset, e.main_internal_return_ptr, e.main_l1_to_l2_msg_exists_write_offset, e.main_l2_gas_remaining, e.main_note_hash_exist_write_offset, e.main_nullifier_exists_write_offset, e.main_nullifier_non_exists_write_offset, e.main_pc, e.main_sel_execution_row, e.main_sload_write_offset, e.main_sstore_write_offset, e.mem_glob_addr, e.mem_rw, e.mem_sel_mem, e.mem_tag, e.mem_tsp, e.mem_val, e.slice_addr, e.slice_clk, e.slice_cnt, e.slice_col_offset, e.slice_sel_cd_cpy, e.slice_sel_mem_active, e.slice_sel_return, e.slice_sel_start, e.slice_space_id @@ -118,12 +118,12 @@ class AvmFlavor { static constexpr bool HasZK = false; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 16; - static constexpr size_t NUM_WITNESS_ENTITIES = 680; + static constexpr size_t NUM_WITNESS_ENTITIES = 679; static constexpr size_t NUM_SHIFTED_ENTITIES = 46; static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 742; + static constexpr size_t NUM_ALL_ENTITIES = 741; // The total number of witnesses including shifts and derived entities. static constexpr size_t NUM_ALL_WITNESS_ENTITIES = NUM_WITNESS_ENTITIES + NUM_SHIFTED_ENTITIES; @@ -315,10 +315,12 @@ class AvmFlavor { class VerificationKey : public VerificationKey_, VerifierCommitmentKey> { public: + using FF = VerificationKey_::FF; + VerificationKey() = default; VerificationKey(const std::shared_ptr& proving_key) - : VerificationKey_(proving_key->circuit_size, proving_key->num_public_inputs) + : VerificationKey_(proving_key->circuit_size, static_cast(proving_key->num_public_inputs)) { for (auto [polynomial, commitment] : zip_view(proving_key->get_precomputed_polynomials(), this->get_all())) { @@ -337,6 +339,8 @@ class AvmFlavor { } pcs_verification_key = std::make_shared(); } + + std::vector to_field_elements() const; }; class AllValues : public AllEntities { diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.cpp index 01ac46e02d8..1f465d4098c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.cpp @@ -203,7 +203,6 @@ template std::vector AvmFullRow::names() "main_sel_op_cast", "main_sel_op_chain_id", "main_sel_op_cmov", - "main_sel_op_coinbase", "main_sel_op_dagasleft", "main_sel_op_div", "main_sel_op_ecadd", @@ -904,7 +903,6 @@ template RefVector AvmFullRow::as_vector() const main_sel_op_cast, main_sel_op_chain_id, main_sel_op_cmov, - main_sel_op_coinbase, main_sel_op_dagasleft, main_sel_op_div, main_sel_op_ecadd, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp index bf958cce1b4..c4bbe015e9c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp @@ -194,7 +194,6 @@ template struct AvmFullRow { FF main_sel_op_cast{}; FF main_sel_op_chain_id{}; FF main_sel_op_cmov{}; - FF main_sel_op_coinbase{}; FF main_sel_op_dagasleft{}; FF main_sel_op_div{}; FF main_sel_op_ecadd{}; @@ -710,7 +709,7 @@ template struct AvmFullRow { RefVector as_vector() const; static std::vector names(); - static constexpr size_t SIZE = 696; + static constexpr size_t SIZE = 695; }; template std::ostream& operator<<(std::ostream& os, AvmFullRow const& row); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/kernel.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/kernel.hpp index 4ac010e7171..1542c964bff 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/kernel.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/kernel.hpp @@ -10,9 +10,9 @@ template class kernelImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; template void static accumulate(ContainerOverSubrelations& evals, @@ -28,7 +28,6 @@ template class kernelImpl { const auto constants_VERSION_SELECTOR = FF(30); const auto constants_BLOCK_NUMBER_SELECTOR = FF(31); const auto constants_TIMESTAMP_SELECTOR = FF(33); - const auto constants_COINBASE_SELECTOR = FF(34); const auto constants_FEE_PER_DA_GAS_SELECTOR = FF(36); const auto constants_FEE_PER_L2_GAS_SELECTOR = FF(37); const auto constants_TRANSACTION_FEE_SELECTOR = FF(41); @@ -43,14 +42,13 @@ template class kernelImpl { const auto constants_START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET = FF(160); const auto constants_START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET = FF(162); const auto main_KERNEL_INPUT_SELECTORS = - (((((((((((new_term.main_sel_op_address + new_term.main_sel_op_storage_address) + - new_term.main_sel_op_sender) + - new_term.main_sel_op_function_selector) + - new_term.main_sel_op_transaction_fee) + - new_term.main_sel_op_chain_id) + - new_term.main_sel_op_version) + - new_term.main_sel_op_block_number) + - new_term.main_sel_op_coinbase) + + ((((((((((new_term.main_sel_op_address + new_term.main_sel_op_storage_address) + + new_term.main_sel_op_sender) + + new_term.main_sel_op_function_selector) + + new_term.main_sel_op_transaction_fee) + + new_term.main_sel_op_chain_id) + + new_term.main_sel_op_version) + + new_term.main_sel_op_block_number) + new_term.main_sel_op_timestamp) + new_term.main_sel_op_fee_per_l2_gas) + new_term.main_sel_op_fee_per_da_gas); @@ -208,54 +206,48 @@ template class kernelImpl { } { using Accumulator = typename std::tuple_element_t<19, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_coinbase * (new_term.main_kernel_in_offset - constants_COINBASE_SELECTOR)); - tmp *= scaling_factor; - std::get<19>(evals) += typename Accumulator::View(tmp); - } - { - using Accumulator = typename std::tuple_element_t<20, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_fee_per_da_gas * (new_term.main_kernel_in_offset - constants_FEE_PER_DA_GAS_SELECTOR)); tmp *= scaling_factor; - std::get<20>(evals) += typename Accumulator::View(tmp); + std::get<19>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<21, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<20, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_fee_per_l2_gas * (new_term.main_kernel_in_offset - constants_FEE_PER_L2_GAS_SELECTOR)); tmp *= scaling_factor; - std::get<21>(evals) += typename Accumulator::View(tmp); + std::get<20>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<22, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<21, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_note_hash_exists * (new_term.main_kernel_out_offset - (constants_START_NOTE_HASH_EXISTS_WRITE_OFFSET + new_term.main_note_hash_exist_write_offset))); tmp *= scaling_factor; - std::get<22>(evals) += typename Accumulator::View(tmp); + std::get<21>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<23, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<22, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_first * new_term.main_note_hash_exist_write_offset); tmp *= scaling_factor; - std::get<23>(evals) += typename Accumulator::View(tmp); + std::get<22>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<24, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<23, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_emit_note_hash * (new_term.main_kernel_out_offset - (constants_START_EMIT_NOTE_HASH_WRITE_OFFSET + new_term.main_emit_note_hash_write_offset))); tmp *= scaling_factor; - std::get<24>(evals) += typename Accumulator::View(tmp); + std::get<23>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<25, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<24, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_first * new_term.main_emit_note_hash_write_offset); tmp *= scaling_factor; - std::get<25>(evals) += typename Accumulator::View(tmp); + std::get<24>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<26, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<25, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_nullifier_exists * (new_term.main_kernel_out_offset - ((new_term.main_ib * @@ -263,115 +255,115 @@ template class kernelImpl { ((FF(1) - new_term.main_ib) * (constants_START_NULLIFIER_NON_EXISTS_OFFSET + new_term.main_nullifier_non_exists_write_offset))))); tmp *= scaling_factor; - std::get<26>(evals) += typename Accumulator::View(tmp); + std::get<25>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<27, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<26, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_first * new_term.main_nullifier_exists_write_offset); tmp *= scaling_factor; - std::get<27>(evals) += typename Accumulator::View(tmp); + std::get<26>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<28, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<27, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_first * new_term.main_nullifier_non_exists_write_offset); tmp *= scaling_factor; - std::get<28>(evals) += typename Accumulator::View(tmp); + std::get<27>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<29, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<28, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_emit_nullifier * (new_term.main_kernel_out_offset - (constants_START_EMIT_NULLIFIER_WRITE_OFFSET + new_term.main_emit_nullifier_write_offset))); tmp *= scaling_factor; - std::get<29>(evals) += typename Accumulator::View(tmp); + std::get<28>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<30, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<29, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_first * new_term.main_emit_nullifier_write_offset); tmp *= scaling_factor; - std::get<30>(evals) += typename Accumulator::View(tmp); + std::get<29>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<31, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<30, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_l1_to_l2_msg_exists * (new_term.main_kernel_out_offset - (constants_START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET + new_term.main_l1_to_l2_msg_exists_write_offset))); tmp *= scaling_factor; - std::get<31>(evals) += typename Accumulator::View(tmp); + std::get<30>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<32, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<31, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_first * new_term.main_l1_to_l2_msg_exists_write_offset); tmp *= scaling_factor; - std::get<32>(evals) += typename Accumulator::View(tmp); + std::get<31>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<33, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<32, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_emit_unencrypted_log * (new_term.main_kernel_out_offset - (constants_START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET + new_term.main_emit_unencrypted_log_write_offset))); tmp *= scaling_factor; - std::get<33>(evals) += typename Accumulator::View(tmp); + std::get<32>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<34, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<33, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_first * new_term.main_emit_unencrypted_log_write_offset); tmp *= scaling_factor; - std::get<34>(evals) += typename Accumulator::View(tmp); + std::get<33>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<35, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<34, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_emit_l2_to_l1_msg * (new_term.main_kernel_out_offset - (constants_START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET + new_term.main_emit_l2_to_l1_msg_write_offset))); tmp *= scaling_factor; - std::get<35>(evals) += typename Accumulator::View(tmp); + std::get<34>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<36, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<35, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_first * new_term.main_emit_l2_to_l1_msg_write_offset); tmp *= scaling_factor; - std::get<36>(evals) += typename Accumulator::View(tmp); + std::get<35>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<37, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<36, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_sload * (new_term.main_kernel_out_offset - (constants_START_SLOAD_WRITE_OFFSET + new_term.main_sload_write_offset))); tmp *= scaling_factor; - std::get<37>(evals) += typename Accumulator::View(tmp); + std::get<36>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<38, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<37, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_first * new_term.main_sload_write_offset); tmp *= scaling_factor; - std::get<38>(evals) += typename Accumulator::View(tmp); + std::get<37>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<39, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<38, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_sstore * (new_term.main_kernel_out_offset - (constants_START_SSTORE_WRITE_OFFSET + new_term.main_sstore_write_offset))); tmp *= scaling_factor; - std::get<39>(evals) += typename Accumulator::View(tmp); + std::get<38>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<40, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<39, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_first * new_term.main_sstore_write_offset); tmp *= scaling_factor; - std::get<40>(evals) += typename Accumulator::View(tmp); + std::get<39>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<41, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<40, ContainerOverSubrelations>; auto tmp = (main_KERNEL_INPUT_SELECTORS * (FF(1) - new_term.main_sel_q_kernel_lookup)); tmp *= scaling_factor; - std::get<41>(evals) += typename Accumulator::View(tmp); + std::get<40>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<42, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<41, ContainerOverSubrelations>; auto tmp = (main_KERNEL_OUTPUT_SELECTORS * (FF(1) - new_term.main_sel_q_kernel_output_lookup)); tmp *= scaling_factor; - std::get<42>(evals) += typename Accumulator::View(tmp); + std::get<41>(evals) += typename Accumulator::View(tmp); } } }; @@ -422,32 +414,30 @@ template class kernel : public Relation> { case 18: return "TIMESTAMP_KERNEL"; case 19: - return "COINBASE_KERNEL"; - case 20: return "FEE_DA_GAS_KERNEL"; - case 21: + case 20: return "FEE_L2_GAS_KERNEL"; - case 22: + case 21: return "NOTE_HASH_KERNEL_OUTPUT"; - case 24: + case 23: return "EMIT_NOTE_HASH_KERNEL_OUTPUT"; - case 26: + case 25: return "NULLIFIER_EXISTS_KERNEL_OUTPUT"; - case 29: + case 28: return "EMIT_NULLIFIER_KERNEL_OUTPUT"; - case 31: + case 30: return "L1_TO_L2_MSG_EXISTS_KERNEL_OUTPUT"; - case 33: + case 32: return "EMIT_UNENCRYPTED_LOG_KERNEL_OUTPUT"; - case 35: + case 34: return "EMIT_L2_TO_L1_MSGS_KERNEL_OUTPUT"; - case 37: + case 36: return "SLOAD_KERNEL_OUTPUT"; - case 39: + case 38: return "SSTORE_KERNEL_OUTPUT"; - case 41: + case 40: return "KERNEL_INPUT_ACTIVE_CHECK"; - case 42: + case 41: return "KERNEL_OUTPUT_ACTIVE_CHECK"; } return std::to_string(index); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/main.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/main.hpp index 0c62e3d4004..146bb6d1bc2 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/main.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/main.hpp @@ -10,11 +10,11 @@ template class mainImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 3, 3, 3, 4, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, 2, 2 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 5, 5, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, 2, 2 }; template @@ -25,14 +25,13 @@ template class mainImpl { { const auto constants_misc_INTERNAL_CALL_SPACE_ID = FF(255); const auto main_KERNEL_INPUT_SELECTORS = - (((((((((((new_term.main_sel_op_address + new_term.main_sel_op_storage_address) + - new_term.main_sel_op_sender) + - new_term.main_sel_op_function_selector) + - new_term.main_sel_op_transaction_fee) + - new_term.main_sel_op_chain_id) + - new_term.main_sel_op_version) + - new_term.main_sel_op_block_number) + - new_term.main_sel_op_coinbase) + + ((((((((((new_term.main_sel_op_address + new_term.main_sel_op_storage_address) + + new_term.main_sel_op_sender) + + new_term.main_sel_op_function_selector) + + new_term.main_sel_op_transaction_fee) + + new_term.main_sel_op_chain_id) + + new_term.main_sel_op_version) + + new_term.main_sel_op_block_number) + new_term.main_sel_op_timestamp) + new_term.main_sel_op_fee_per_l2_gas) + new_term.main_sel_op_fee_per_da_gas); @@ -148,651 +147,645 @@ template class mainImpl { } { using Accumulator = typename std::tuple_element_t<10, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_coinbase * (FF(1) - new_term.main_sel_op_coinbase)); + auto tmp = (new_term.main_sel_op_timestamp * (FF(1) - new_term.main_sel_op_timestamp)); tmp *= scaling_factor; std::get<10>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<11, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_timestamp * (FF(1) - new_term.main_sel_op_timestamp)); + auto tmp = (new_term.main_sel_op_fee_per_l2_gas * (FF(1) - new_term.main_sel_op_fee_per_l2_gas)); tmp *= scaling_factor; std::get<11>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<12, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_fee_per_l2_gas * (FF(1) - new_term.main_sel_op_fee_per_l2_gas)); + auto tmp = (new_term.main_sel_op_fee_per_da_gas * (FF(1) - new_term.main_sel_op_fee_per_da_gas)); tmp *= scaling_factor; std::get<12>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<13, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_fee_per_da_gas * (FF(1) - new_term.main_sel_op_fee_per_da_gas)); + auto tmp = (new_term.main_sel_op_l2gasleft * (FF(1) - new_term.main_sel_op_l2gasleft)); tmp *= scaling_factor; std::get<13>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<14, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_l2gasleft * (FF(1) - new_term.main_sel_op_l2gasleft)); + auto tmp = (new_term.main_sel_op_dagasleft * (FF(1) - new_term.main_sel_op_dagasleft)); tmp *= scaling_factor; std::get<14>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<15, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_dagasleft * (FF(1) - new_term.main_sel_op_dagasleft)); + auto tmp = (new_term.main_sel_op_note_hash_exists * (FF(1) - new_term.main_sel_op_note_hash_exists)); tmp *= scaling_factor; std::get<15>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<16, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_note_hash_exists * (FF(1) - new_term.main_sel_op_note_hash_exists)); + auto tmp = (new_term.main_sel_op_emit_note_hash * (FF(1) - new_term.main_sel_op_emit_note_hash)); tmp *= scaling_factor; std::get<16>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<17, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_emit_note_hash * (FF(1) - new_term.main_sel_op_emit_note_hash)); + auto tmp = (new_term.main_sel_op_nullifier_exists * (FF(1) - new_term.main_sel_op_nullifier_exists)); tmp *= scaling_factor; std::get<17>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<18, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_nullifier_exists * (FF(1) - new_term.main_sel_op_nullifier_exists)); + auto tmp = (new_term.main_sel_op_emit_nullifier * (FF(1) - new_term.main_sel_op_emit_nullifier)); tmp *= scaling_factor; std::get<18>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<19, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_emit_nullifier * (FF(1) - new_term.main_sel_op_emit_nullifier)); + auto tmp = (new_term.main_sel_op_l1_to_l2_msg_exists * (FF(1) - new_term.main_sel_op_l1_to_l2_msg_exists)); tmp *= scaling_factor; std::get<19>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<20, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_l1_to_l2_msg_exists * (FF(1) - new_term.main_sel_op_l1_to_l2_msg_exists)); + auto tmp = + (new_term.main_sel_op_emit_unencrypted_log * (FF(1) - new_term.main_sel_op_emit_unencrypted_log)); tmp *= scaling_factor; std::get<20>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<21, ContainerOverSubrelations>; - auto tmp = - (new_term.main_sel_op_emit_unencrypted_log * (FF(1) - new_term.main_sel_op_emit_unencrypted_log)); + auto tmp = (new_term.main_sel_op_emit_l2_to_l1_msg * (FF(1) - new_term.main_sel_op_emit_l2_to_l1_msg)); tmp *= scaling_factor; std::get<21>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<22, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_emit_l2_to_l1_msg * (FF(1) - new_term.main_sel_op_emit_l2_to_l1_msg)); + auto tmp = + (new_term.main_sel_op_get_contract_instance * (FF(1) - new_term.main_sel_op_get_contract_instance)); tmp *= scaling_factor; std::get<22>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<23, ContainerOverSubrelations>; - auto tmp = - (new_term.main_sel_op_get_contract_instance * (FF(1) - new_term.main_sel_op_get_contract_instance)); + auto tmp = (new_term.main_sel_op_sload * (FF(1) - new_term.main_sel_op_sload)); tmp *= scaling_factor; std::get<23>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<24, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_sload * (FF(1) - new_term.main_sel_op_sload)); + auto tmp = (new_term.main_sel_op_sstore * (FF(1) - new_term.main_sel_op_sstore)); tmp *= scaling_factor; std::get<24>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<25, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_sstore * (FF(1) - new_term.main_sel_op_sstore)); + auto tmp = (new_term.main_sel_op_radix_le * (FF(1) - new_term.main_sel_op_radix_le)); tmp *= scaling_factor; std::get<25>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<26, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_radix_le * (FF(1) - new_term.main_sel_op_radix_le)); + auto tmp = (new_term.main_sel_op_sha256 * (FF(1) - new_term.main_sel_op_sha256)); tmp *= scaling_factor; std::get<26>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<27, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_sha256 * (FF(1) - new_term.main_sel_op_sha256)); + auto tmp = (new_term.main_sel_op_poseidon2 * (FF(1) - new_term.main_sel_op_poseidon2)); tmp *= scaling_factor; std::get<27>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<28, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_poseidon2 * (FF(1) - new_term.main_sel_op_poseidon2)); + auto tmp = (new_term.main_sel_op_keccak * (FF(1) - new_term.main_sel_op_keccak)); tmp *= scaling_factor; std::get<28>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<29, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_keccak * (FF(1) - new_term.main_sel_op_keccak)); + auto tmp = (new_term.main_sel_op_pedersen * (FF(1) - new_term.main_sel_op_pedersen)); tmp *= scaling_factor; std::get<29>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<30, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_pedersen * (FF(1) - new_term.main_sel_op_pedersen)); + auto tmp = (new_term.main_sel_op_ecadd * (FF(1) - new_term.main_sel_op_ecadd)); tmp *= scaling_factor; std::get<30>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<31, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_ecadd * (FF(1) - new_term.main_sel_op_ecadd)); + auto tmp = (new_term.main_sel_op_pedersen_commit * (FF(1) - new_term.main_sel_op_pedersen_commit)); tmp *= scaling_factor; std::get<31>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<32, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_pedersen_commit * (FF(1) - new_term.main_sel_op_pedersen_commit)); + auto tmp = (new_term.main_sel_op_msm * (FF(1) - new_term.main_sel_op_msm)); tmp *= scaling_factor; std::get<32>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<33, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_msm * (FF(1) - new_term.main_sel_op_msm)); + auto tmp = (new_term.main_sel_op_add * (FF(1) - new_term.main_sel_op_add)); tmp *= scaling_factor; std::get<33>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<34, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_add * (FF(1) - new_term.main_sel_op_add)); + auto tmp = (new_term.main_sel_op_sub * (FF(1) - new_term.main_sel_op_sub)); tmp *= scaling_factor; std::get<34>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<35, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_sub * (FF(1) - new_term.main_sel_op_sub)); + auto tmp = (new_term.main_sel_op_mul * (FF(1) - new_term.main_sel_op_mul)); tmp *= scaling_factor; std::get<35>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<36, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_mul * (FF(1) - new_term.main_sel_op_mul)); + auto tmp = (new_term.main_sel_op_div * (FF(1) - new_term.main_sel_op_div)); tmp *= scaling_factor; std::get<36>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<37, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_div * (FF(1) - new_term.main_sel_op_div)); + auto tmp = (new_term.main_sel_op_fdiv * (FF(1) - new_term.main_sel_op_fdiv)); tmp *= scaling_factor; std::get<37>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<38, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_fdiv * (FF(1) - new_term.main_sel_op_fdiv)); + auto tmp = (new_term.main_sel_op_not * (FF(1) - new_term.main_sel_op_not)); tmp *= scaling_factor; std::get<38>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<39, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_not * (FF(1) - new_term.main_sel_op_not)); + auto tmp = (new_term.main_sel_op_eq * (FF(1) - new_term.main_sel_op_eq)); tmp *= scaling_factor; std::get<39>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<40, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_eq * (FF(1) - new_term.main_sel_op_eq)); + auto tmp = (new_term.main_sel_op_and * (FF(1) - new_term.main_sel_op_and)); tmp *= scaling_factor; std::get<40>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<41, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_and * (FF(1) - new_term.main_sel_op_and)); + auto tmp = (new_term.main_sel_op_or * (FF(1) - new_term.main_sel_op_or)); tmp *= scaling_factor; std::get<41>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<42, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_or * (FF(1) - new_term.main_sel_op_or)); + auto tmp = (new_term.main_sel_op_xor * (FF(1) - new_term.main_sel_op_xor)); tmp *= scaling_factor; std::get<42>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<43, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_xor * (FF(1) - new_term.main_sel_op_xor)); + auto tmp = (new_term.main_sel_op_cast * (FF(1) - new_term.main_sel_op_cast)); tmp *= scaling_factor; std::get<43>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<44, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_cast * (FF(1) - new_term.main_sel_op_cast)); + auto tmp = (new_term.main_sel_op_lt * (FF(1) - new_term.main_sel_op_lt)); tmp *= scaling_factor; std::get<44>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<45, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_lt * (FF(1) - new_term.main_sel_op_lt)); + auto tmp = (new_term.main_sel_op_lte * (FF(1) - new_term.main_sel_op_lte)); tmp *= scaling_factor; std::get<45>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<46, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_lte * (FF(1) - new_term.main_sel_op_lte)); + auto tmp = (new_term.main_sel_op_shl * (FF(1) - new_term.main_sel_op_shl)); tmp *= scaling_factor; std::get<46>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<47, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_shl * (FF(1) - new_term.main_sel_op_shl)); + auto tmp = (new_term.main_sel_op_shr * (FF(1) - new_term.main_sel_op_shr)); tmp *= scaling_factor; std::get<47>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<48, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_shr * (FF(1) - new_term.main_sel_op_shr)); + auto tmp = (new_term.main_sel_op_internal_call * (FF(1) - new_term.main_sel_op_internal_call)); tmp *= scaling_factor; std::get<48>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<49, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * (FF(1) - new_term.main_sel_op_internal_call)); + auto tmp = (new_term.main_sel_op_internal_return * (FF(1) - new_term.main_sel_op_internal_return)); tmp *= scaling_factor; std::get<49>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<50, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_return * (FF(1) - new_term.main_sel_op_internal_return)); + auto tmp = (new_term.main_sel_op_jump * (FF(1) - new_term.main_sel_op_jump)); tmp *= scaling_factor; std::get<50>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<51, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_jump * (FF(1) - new_term.main_sel_op_jump)); + auto tmp = (new_term.main_sel_op_jumpi * (FF(1) - new_term.main_sel_op_jumpi)); tmp *= scaling_factor; std::get<51>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<52, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_jumpi * (FF(1) - new_term.main_sel_op_jumpi)); + auto tmp = (new_term.main_sel_op_external_call * (FF(1) - new_term.main_sel_op_external_call)); tmp *= scaling_factor; std::get<52>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<53, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_external_call * (FF(1) - new_term.main_sel_op_external_call)); + auto tmp = (new_term.main_sel_op_calldata_copy * (FF(1) - new_term.main_sel_op_calldata_copy)); tmp *= scaling_factor; std::get<53>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<54, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_calldata_copy * (FF(1) - new_term.main_sel_op_calldata_copy)); + auto tmp = (new_term.main_sel_op_external_return * (FF(1) - new_term.main_sel_op_external_return)); tmp *= scaling_factor; std::get<54>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<55, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_external_return * (FF(1) - new_term.main_sel_op_external_return)); + auto tmp = (new_term.main_sel_op_external_revert * (FF(1) - new_term.main_sel_op_external_revert)); tmp *= scaling_factor; std::get<55>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<56, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_external_revert * (FF(1) - new_term.main_sel_op_external_revert)); + auto tmp = (new_term.main_sel_op_set * (FF(1) - new_term.main_sel_op_set)); tmp *= scaling_factor; std::get<56>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<57, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_set * (FF(1) - new_term.main_sel_op_set)); + auto tmp = (new_term.main_sel_op_mov * (FF(1) - new_term.main_sel_op_mov)); tmp *= scaling_factor; std::get<57>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<58, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_mov * (FF(1) - new_term.main_sel_op_mov)); + auto tmp = (new_term.main_sel_op_cmov * (FF(1) - new_term.main_sel_op_cmov)); tmp *= scaling_factor; std::get<58>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<59, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_cmov * (FF(1) - new_term.main_sel_op_cmov)); + auto tmp = (new_term.main_op_err * (FF(1) - new_term.main_op_err)); tmp *= scaling_factor; std::get<59>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<60, ContainerOverSubrelations>; - auto tmp = (new_term.main_op_err * (FF(1) - new_term.main_op_err)); + auto tmp = (new_term.main_tag_err * (FF(1) - new_term.main_tag_err)); tmp *= scaling_factor; std::get<60>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<61, ContainerOverSubrelations>; - auto tmp = (new_term.main_tag_err * (FF(1) - new_term.main_tag_err)); + auto tmp = (new_term.main_id_zero * (FF(1) - new_term.main_id_zero)); tmp *= scaling_factor; std::get<61>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<62, ContainerOverSubrelations>; - auto tmp = (new_term.main_id_zero * (FF(1) - new_term.main_id_zero)); + auto tmp = (new_term.main_sel_mem_op_a * (FF(1) - new_term.main_sel_mem_op_a)); tmp *= scaling_factor; std::get<62>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<63, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mem_op_a * (FF(1) - new_term.main_sel_mem_op_a)); + auto tmp = (new_term.main_sel_mem_op_b * (FF(1) - new_term.main_sel_mem_op_b)); tmp *= scaling_factor; std::get<63>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<64, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mem_op_b * (FF(1) - new_term.main_sel_mem_op_b)); + auto tmp = (new_term.main_sel_mem_op_c * (FF(1) - new_term.main_sel_mem_op_c)); tmp *= scaling_factor; std::get<64>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<65, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mem_op_c * (FF(1) - new_term.main_sel_mem_op_c)); + auto tmp = (new_term.main_sel_mem_op_d * (FF(1) - new_term.main_sel_mem_op_d)); tmp *= scaling_factor; std::get<65>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<66, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mem_op_d * (FF(1) - new_term.main_sel_mem_op_d)); + auto tmp = (new_term.main_rwa * (FF(1) - new_term.main_rwa)); tmp *= scaling_factor; std::get<66>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<67, ContainerOverSubrelations>; - auto tmp = (new_term.main_rwa * (FF(1) - new_term.main_rwa)); + auto tmp = (new_term.main_rwb * (FF(1) - new_term.main_rwb)); tmp *= scaling_factor; std::get<67>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<68, ContainerOverSubrelations>; - auto tmp = (new_term.main_rwb * (FF(1) - new_term.main_rwb)); + auto tmp = (new_term.main_rwc * (FF(1) - new_term.main_rwc)); tmp *= scaling_factor; std::get<68>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<69, ContainerOverSubrelations>; - auto tmp = (new_term.main_rwc * (FF(1) - new_term.main_rwc)); + auto tmp = (new_term.main_rwd * (FF(1) - new_term.main_rwd)); tmp *= scaling_factor; std::get<69>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<70, ContainerOverSubrelations>; - auto tmp = (new_term.main_rwd * (FF(1) - new_term.main_rwd)); + auto tmp = (new_term.main_sel_resolve_ind_addr_a * (FF(1) - new_term.main_sel_resolve_ind_addr_a)); tmp *= scaling_factor; std::get<70>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<71, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_resolve_ind_addr_a * (FF(1) - new_term.main_sel_resolve_ind_addr_a)); + auto tmp = (new_term.main_sel_resolve_ind_addr_b * (FF(1) - new_term.main_sel_resolve_ind_addr_b)); tmp *= scaling_factor; std::get<71>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<72, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_resolve_ind_addr_b * (FF(1) - new_term.main_sel_resolve_ind_addr_b)); + auto tmp = (new_term.main_sel_resolve_ind_addr_c * (FF(1) - new_term.main_sel_resolve_ind_addr_c)); tmp *= scaling_factor; std::get<72>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<73, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_resolve_ind_addr_c * (FF(1) - new_term.main_sel_resolve_ind_addr_c)); + auto tmp = (new_term.main_sel_resolve_ind_addr_d * (FF(1) - new_term.main_sel_resolve_ind_addr_d)); tmp *= scaling_factor; std::get<73>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<74, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_resolve_ind_addr_d * (FF(1) - new_term.main_sel_resolve_ind_addr_d)); + auto tmp = (((new_term.main_sel_op_eq + new_term.main_sel_op_lte) + new_term.main_sel_op_lt) * + (new_term.main_w_in_tag - FF(1))); tmp *= scaling_factor; std::get<74>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<75, ContainerOverSubrelations>; - auto tmp = (((new_term.main_sel_op_eq + new_term.main_sel_op_lte) + new_term.main_sel_op_lt) * - (new_term.main_w_in_tag - FF(1))); + auto tmp = ((new_term.main_sel_op_fdiv * (FF(1) - new_term.main_op_err)) * + ((new_term.main_ic * new_term.main_ib) - new_term.main_ia)); tmp *= scaling_factor; std::get<75>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<76, ContainerOverSubrelations>; - auto tmp = ((new_term.main_sel_op_fdiv * (FF(1) - new_term.main_op_err)) * - ((new_term.main_ic * new_term.main_ib) - new_term.main_ia)); + auto tmp = ((new_term.main_sel_op_fdiv + new_term.main_sel_op_div) * + (((new_term.main_ib * new_term.main_inv) - FF(1)) + new_term.main_op_err)); tmp *= scaling_factor; std::get<76>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<77, ContainerOverSubrelations>; - auto tmp = ((new_term.main_sel_op_fdiv + new_term.main_sel_op_div) * - (((new_term.main_ib * new_term.main_inv) - FF(1)) + new_term.main_op_err)); + auto tmp = (((new_term.main_sel_op_fdiv + new_term.main_sel_op_div) * new_term.main_op_err) * + (FF(1) - new_term.main_inv)); tmp *= scaling_factor; std::get<77>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<78, ContainerOverSubrelations>; - auto tmp = (((new_term.main_sel_op_fdiv + new_term.main_sel_op_div) * new_term.main_op_err) * - (FF(1) - new_term.main_inv)); + auto tmp = (new_term.main_sel_op_fdiv * (new_term.main_r_in_tag - FF(6))); tmp *= scaling_factor; std::get<78>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<79, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_fdiv * (new_term.main_r_in_tag - FF(6))); + auto tmp = (new_term.main_sel_op_fdiv * (new_term.main_w_in_tag - FF(6))); tmp *= scaling_factor; std::get<79>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<80, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_fdiv * (new_term.main_w_in_tag - FF(6))); + auto tmp = (new_term.main_op_err * ((new_term.main_sel_op_fdiv + new_term.main_sel_op_div) - FF(1))); tmp *= scaling_factor; std::get<80>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<81, ContainerOverSubrelations>; - auto tmp = (new_term.main_op_err * ((new_term.main_sel_op_fdiv + new_term.main_sel_op_div) - FF(1))); + auto tmp = (new_term.main_sel_op_jump * (new_term.main_pc_shift - new_term.main_ia)); tmp *= scaling_factor; std::get<81>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<82, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_jump * (new_term.main_pc_shift - new_term.main_ia)); + auto tmp = (new_term.main_sel_op_jumpi * + (((FF(1) - new_term.main_id_zero) * (new_term.main_pc_shift - new_term.main_ia)) + + (new_term.main_id_zero * ((new_term.main_pc_shift - new_term.main_pc) - FF(1))))); tmp *= scaling_factor; std::get<82>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<83, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_jumpi * - (((FF(1) - new_term.main_id_zero) * (new_term.main_pc_shift - new_term.main_ia)) + - (new_term.main_id_zero * ((new_term.main_pc_shift - new_term.main_pc) - FF(1))))); + auto tmp = (new_term.main_sel_op_internal_call * + (new_term.main_internal_return_ptr_shift - (new_term.main_internal_return_ptr + FF(1)))); tmp *= scaling_factor; std::get<83>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<84, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * - (new_term.main_internal_return_ptr_shift - (new_term.main_internal_return_ptr + FF(1)))); + auto tmp = + (new_term.main_sel_op_internal_call * (new_term.main_internal_return_ptr - new_term.main_mem_addr_b)); tmp *= scaling_factor; std::get<84>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<85, ContainerOverSubrelations>; - auto tmp = - (new_term.main_sel_op_internal_call * (new_term.main_internal_return_ptr - new_term.main_mem_addr_b)); + auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_pc_shift - new_term.main_ia)); tmp *= scaling_factor; std::get<85>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<86, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_pc_shift - new_term.main_ia)); + auto tmp = (new_term.main_sel_op_internal_call * ((new_term.main_pc + FF(1)) - new_term.main_ib)); tmp *= scaling_factor; std::get<86>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<87, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * ((new_term.main_pc + FF(1)) - new_term.main_ib)); + auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_rwb - FF(1))); tmp *= scaling_factor; std::get<87>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<88, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_rwb - FF(1))); + auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_sel_mem_op_b - FF(1))); tmp *= scaling_factor; std::get<88>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<89, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_sel_mem_op_b - FF(1))); + auto tmp = (new_term.main_sel_op_internal_return * + (new_term.main_internal_return_ptr_shift - (new_term.main_internal_return_ptr - FF(1)))); tmp *= scaling_factor; std::get<89>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<90, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_internal_return * - (new_term.main_internal_return_ptr_shift - (new_term.main_internal_return_ptr - FF(1)))); + ((new_term.main_internal_return_ptr - FF(1)) - new_term.main_mem_addr_a)); tmp *= scaling_factor; std::get<90>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<91, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_return * - ((new_term.main_internal_return_ptr - FF(1)) - new_term.main_mem_addr_a)); + auto tmp = (new_term.main_sel_op_internal_return * (new_term.main_pc_shift - new_term.main_ia)); tmp *= scaling_factor; std::get<91>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<92, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_return * (new_term.main_pc_shift - new_term.main_ia)); + auto tmp = (new_term.main_sel_op_internal_return * new_term.main_rwa); tmp *= scaling_factor; std::get<92>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<93, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_return * new_term.main_rwa); + auto tmp = (new_term.main_sel_op_internal_return * (new_term.main_sel_mem_op_a - FF(1))); tmp *= scaling_factor; std::get<93>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<94, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_return * (new_term.main_sel_mem_op_a - FF(1))); + auto tmp = ((main_CUR_AND_NEXT_ARE_MAIN * (FF(1) - main_SEL_ALL_CTRL_FLOW)) * + (new_term.main_pc_shift - (new_term.main_pc + FF(1)))); tmp *= scaling_factor; std::get<94>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<95, ContainerOverSubrelations>; auto tmp = ((main_CUR_AND_NEXT_ARE_MAIN * (FF(1) - main_SEL_ALL_CTRL_FLOW)) * - (new_term.main_pc_shift - (new_term.main_pc + FF(1)))); + (new_term.main_internal_return_ptr_shift - new_term.main_internal_return_ptr)); tmp *= scaling_factor; std::get<95>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<96, ContainerOverSubrelations>; - auto tmp = ((main_CUR_AND_NEXT_ARE_MAIN * (FF(1) - main_SEL_ALL_CTRL_FLOW)) * - (new_term.main_internal_return_ptr_shift - new_term.main_internal_return_ptr)); + auto tmp = ((new_term.main_sel_op_internal_call + new_term.main_sel_op_internal_return) * + (new_term.main_space_id - constants_misc_INTERNAL_CALL_SPACE_ID)); tmp *= scaling_factor; std::get<96>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<97, ContainerOverSubrelations>; - auto tmp = ((new_term.main_sel_op_internal_call + new_term.main_sel_op_internal_return) * - (new_term.main_space_id - constants_misc_INTERNAL_CALL_SPACE_ID)); + auto tmp = (((FF(1) - new_term.main_sel_op_internal_call) - new_term.main_sel_op_internal_return) * + (new_term.main_call_ptr - new_term.main_space_id)); tmp *= scaling_factor; std::get<97>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<98, ContainerOverSubrelations>; - auto tmp = (((FF(1) - new_term.main_sel_op_internal_call) - new_term.main_sel_op_internal_return) * - (new_term.main_call_ptr - new_term.main_space_id)); + auto tmp = ((new_term.main_sel_op_cmov + new_term.main_sel_op_jumpi) * + (((new_term.main_id * new_term.main_inv) - FF(1)) + new_term.main_id_zero)); tmp *= scaling_factor; std::get<98>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<99, ContainerOverSubrelations>; - auto tmp = ((new_term.main_sel_op_cmov + new_term.main_sel_op_jumpi) * - (((new_term.main_id * new_term.main_inv) - FF(1)) + new_term.main_id_zero)); + auto tmp = (((new_term.main_sel_op_cmov + new_term.main_sel_op_jumpi) * new_term.main_id_zero) * + (FF(1) - new_term.main_inv)); tmp *= scaling_factor; std::get<99>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<100, ContainerOverSubrelations>; - auto tmp = (((new_term.main_sel_op_cmov + new_term.main_sel_op_jumpi) * new_term.main_id_zero) * - (FF(1) - new_term.main_inv)); + auto tmp = (new_term.main_sel_mov_ia_to_ic - + (new_term.main_sel_op_mov + (new_term.main_sel_op_cmov * (FF(1) - new_term.main_id_zero)))); tmp *= scaling_factor; std::get<100>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<101, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mov_ia_to_ic - - (new_term.main_sel_op_mov + (new_term.main_sel_op_cmov * (FF(1) - new_term.main_id_zero)))); + auto tmp = (new_term.main_sel_mov_ib_to_ic - (new_term.main_sel_op_cmov * new_term.main_id_zero)); tmp *= scaling_factor; std::get<101>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<102, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mov_ib_to_ic - (new_term.main_sel_op_cmov * new_term.main_id_zero)); + auto tmp = (new_term.main_sel_mov_ia_to_ic * (new_term.main_ia - new_term.main_ic)); tmp *= scaling_factor; std::get<102>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<103, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mov_ia_to_ic * (new_term.main_ia - new_term.main_ic)); + auto tmp = (new_term.main_sel_mov_ib_to_ic * (new_term.main_ib - new_term.main_ic)); tmp *= scaling_factor; std::get<103>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<104, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mov_ib_to_ic * (new_term.main_ib - new_term.main_ic)); + auto tmp = ((new_term.main_sel_op_mov + new_term.main_sel_op_cmov) * + (new_term.main_r_in_tag - new_term.main_w_in_tag)); tmp *= scaling_factor; std::get<104>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<105, ContainerOverSubrelations>; - auto tmp = ((new_term.main_sel_op_mov + new_term.main_sel_op_cmov) * - (new_term.main_r_in_tag - new_term.main_w_in_tag)); + auto tmp = (new_term.main_sel_alu - + ((main_SEL_ALL_ALU * (FF(1) - new_term.main_tag_err)) * (FF(1) - new_term.main_op_err))); tmp *= scaling_factor; std::get<105>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<106, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_alu - - ((main_SEL_ALL_ALU * (FF(1) - new_term.main_tag_err)) * (FF(1) - new_term.main_op_err))); + auto tmp = (main_SEL_ALU_R_TAG * (new_term.main_alu_in_tag - new_term.main_r_in_tag)); tmp *= scaling_factor; std::get<106>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<107, ContainerOverSubrelations>; - auto tmp = (main_SEL_ALU_R_TAG * (new_term.main_alu_in_tag - new_term.main_r_in_tag)); + auto tmp = (main_SEL_ALU_W_TAG * (new_term.main_alu_in_tag - new_term.main_w_in_tag)); tmp *= scaling_factor; std::get<107>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<108, ContainerOverSubrelations>; - auto tmp = (main_SEL_ALU_W_TAG * (new_term.main_alu_in_tag - new_term.main_w_in_tag)); + auto tmp = (new_term.main_sel_op_l2gasleft * (new_term.main_ia - new_term.main_l2_gas_remaining_shift)); tmp *= scaling_factor; std::get<108>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<109, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_l2gasleft * (new_term.main_ia - new_term.main_l2_gas_remaining_shift)); + auto tmp = (new_term.main_sel_op_dagasleft * (new_term.main_ia - new_term.main_da_gas_remaining_shift)); tmp *= scaling_factor; std::get<109>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<110, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_dagasleft * (new_term.main_ia - new_term.main_da_gas_remaining_shift)); - tmp *= scaling_factor; - std::get<110>(evals) += typename Accumulator::View(tmp); - } - { - using Accumulator = typename std::tuple_element_t<111, ContainerOverSubrelations>; auto tmp = ((new_term.main_ib * (FF(1) - new_term.main_tag_err)) * ((new_term.main_sel_op_calldata_copy + new_term.main_sel_op_external_return) - new_term.main_sel_slice_gadget)); tmp *= scaling_factor; - std::get<111>(evals) += typename Accumulator::View(tmp); + std::get<110>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<112, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<111, ContainerOverSubrelations>; auto tmp = (new_term.main_bin_op_id - (new_term.main_sel_op_or + (FF(2) * new_term.main_sel_op_xor))); tmp *= scaling_factor; - std::get<112>(evals) += typename Accumulator::View(tmp); + std::get<111>(evals) += typename Accumulator::View(tmp); } { - using Accumulator = typename std::tuple_element_t<113, ContainerOverSubrelations>; + using Accumulator = typename std::tuple_element_t<112, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_bin - ((new_term.main_sel_op_and + new_term.main_sel_op_or) + new_term.main_sel_op_xor)); tmp *= scaling_factor; - std::get<113>(evals) += typename Accumulator::View(tmp); + std::get<112>(evals) += typename Accumulator::View(tmp); } } }; @@ -806,53 +799,53 @@ template class main : public Relation> { switch (index) { case 0: return "OPCODE_SELECTORS"; - case 75: + case 74: return "OUTPUT_U8"; - case 76: + case 75: return "SUBOP_FDIV"; - case 77: + case 76: return "SUBOP_FDIV_ZERO_ERR1"; - case 78: + case 77: return "SUBOP_FDIV_ZERO_ERR2"; - case 79: + case 78: return "SUBOP_FDIV_R_IN_TAG_FF"; - case 80: + case 79: return "SUBOP_FDIV_W_IN_TAG_FF"; - case 81: + case 80: return "SUBOP_ERROR_RELEVANT_OP"; - case 82: + case 81: return "PC_JUMP"; - case 83: + case 82: return "PC_JUMPI"; - case 84: + case 83: return "RETURN_POINTER_INCREMENT"; - case 90: + case 89: return "RETURN_POINTER_DECREMENT"; - case 95: + case 94: return "PC_INCREMENT"; - case 96: + case 95: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 97: + case 96: return "SPACE_ID_INTERNAL"; - case 98: + case 97: return "SPACE_ID_STANDARD_OPCODES"; - case 99: + case 98: return "CMOV_CONDITION_RES_1"; - case 100: + case 99: return "CMOV_CONDITION_RES_2"; - case 103: + case 102: return "MOV_SAME_VALUE_A"; - case 104: + case 103: return "MOV_SAME_VALUE_B"; - case 105: + case 104: return "MOV_MAIN_SAME_TAG"; - case 109: + case 108: return "L2GASLEFT"; - case 110: + case 109: return "DAGASLEFT"; - case 112: + case 111: return "BIN_SEL_1"; - case 113: + case 112: return "BIN_SEL_2"; } return std::to_string(index); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_flavor.hpp index 85eda197acb..d20a2496c0d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_flavor.hpp @@ -3,6 +3,7 @@ #include "barretenberg/stdlib/transcript/transcript.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" #include "barretenberg/vm/avm/generated/flavor.hpp" +#include namespace bb { @@ -63,6 +64,34 @@ template class AvmRecursiveFlavor_ { comm = Commitment::from_witness(builder, native_comm); } } + + /** + * @brief Deserialize a verification key from a vector of field elements + * + * @param builder + * @param elements + */ + VerificationKey(CircuitBuilder& builder, std::span elements) + { + size_t num_frs_read = 0; + size_t num_frs_FF = bb::stdlib::field_conversion::calc_num_bn254_frs(); + size_t num_frs_Comm = bb::stdlib::field_conversion::calc_num_bn254_frs(); + + this->circuit_size = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( + builder, elements.subspan(num_frs_read, num_frs_FF)) + .get_value()); + num_frs_read += num_frs_FF; + this->num_public_inputs = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( + builder, elements.subspan(num_frs_read, num_frs_FF)) + .get_value()); + num_frs_read += num_frs_FF; + + for (Commitment& comm : this->get_all()) { + comm = bb::stdlib::field_conversion::convert_from_bn254_frs( + builder, elements.subspan(num_frs_read, num_frs_Comm)); + num_frs_read += num_frs_Comm; + } + } }; using WitnessCommitments = AvmFlavor::WitnessEntities; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.cpp index bd5129a50d5..9148e568668 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.cpp @@ -1,5 +1,6 @@ #include "barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp" #include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" +#include "barretenberg/plonk_honk_shared/types/aggregation_object_type.hpp" #include "barretenberg/transcript/transcript.hpp" namespace bb { @@ -17,9 +18,18 @@ AvmRecursiveVerifier_::AvmRecursiveVerifier_(Builder* builder, const std , builder(builder) {} +template +AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_::verify_proof(const HonkProof& proof, + AggregationObject agg_obj) +{ + StdlibProof stdlib_proof = bb::convert_proof_to_witness(builder, proof); + return verify_proof(stdlib_proof, agg_obj); +} + // TODO(#991): (see https://github.com/AztecProtocol/barretenberg/issues/991) template -std::array AvmRecursiveVerifier_::verify_proof(const HonkProof& proof) +AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_::verify_proof( + const StdlibProof& stdlib_proof, AggregationObject agg_obj) { using Curve = typename Flavor::Curve; using Zeromorph = ZeroMorphVerifier_; @@ -29,7 +39,6 @@ std::array AvmRecursiveVerifier_::veri using RelationParams = ::bb::RelationParameters; using Transcript = typename Flavor::Transcript; - StdlibProof stdlib_proof = bb::convert_proof_to_witness(builder, proof); transcript = std::make_shared(stdlib_proof); RelationParams relation_parameters; @@ -84,10 +93,13 @@ std::array AvmRecursiveVerifier_::veri auto pairing_points = PCS::reduce_verify(opening_claim, transcript); - return pairing_points; - - // Probably we will have to return an aggregation object (see ultra_recursive_verifier.cpp) once we interface - // with noir for public_kernel integration. Follow, the same recipe as in ultra_recursive_verifier.cpp in this case. + pairing_points[0] = pairing_points[0].normalize(); + pairing_points[1] = pairing_points[1].normalize(); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/995): generate this challenge properly. + typename Curve::ScalarField recursion_separator = + Curve::ScalarField::from_witness_index(builder, builder->add_variable(42)); + agg_obj.aggregate(pairing_points, recursion_separator); + return agg_obj; } template class AvmRecursiveVerifier_>; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp index 7c130c7152d..15ddd48f56d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.hpp @@ -1,4 +1,5 @@ #pragma once +#include "barretenberg/stdlib/plonk_recursion/aggregation_state/aggregation_state.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" #include "barretenberg/vm/avm/recursion/avm_recursive_flavor.hpp" @@ -10,21 +11,21 @@ template class AvmRecursiveVerifier_ { using Commitment = typename Flavor::Commitment; using CommitmentLabels = typename Flavor::CommitmentLabels; using RelationSeparator = typename Flavor::RelationSeparator; - using VerificationKey = typename Flavor::VerificationKey; - using NativeVerificationKey = typename Flavor::NativeVerificationKey; using Builder = typename Flavor::CircuitBuilder; using PCS = typename Flavor::PCS; using Transcript = bb::BaseTranscript>; using VerifierCommitments = typename Flavor::VerifierCommitments; + using AggregationObject = bb::stdlib::recursion::aggregation_state; public: explicit AvmRecursiveVerifier_(Builder* builder, const std::shared_ptr& native_verification_key); explicit AvmRecursiveVerifier_(Builder* builder, const std::shared_ptr& vkey); - std::array verify_proof(const HonkProof& proof); + AggregationObject verify_proof(const HonkProof& proof, AggregationObject agg_obj); + AggregationObject verify_proof(const StdlibProof& stdlib_proof, AggregationObject agg_obj); std::shared_ptr key; Builder* builder; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.test.cpp index 7f9a7fd2674..946cd2e15fb 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/recursion/avm_recursive_verifier.test.cpp @@ -2,7 +2,7 @@ #include "barretenberg/circuit_checker/circuit_checker.hpp" #include "barretenberg/numeric/random/engine.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/sumcheck/instance/prover_instance.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" #include "barretenberg/vm/avm/generated/circuit_builder.hpp" @@ -32,12 +32,11 @@ class AvmRecursiveTests : public ::testing::Test { using Transcript = InnerFlavor::Transcript; - // Note: removed templating from eccvm one using RecursiveVerifier = AvmRecursiveVerifier_; using OuterBuilder = typename RecursiveFlavor::CircuitBuilder; - using OuterProver = UltraProver_; - using OuterVerifier = UltraVerifier_; + using OuterProver = UltraProver; + using OuterVerifier = UltraVerifier; using OuterDeciderProvingKey = DeciderProvingKey_; static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } @@ -66,8 +65,8 @@ TEST_F(AvmRecursiveTests, recursion) { AvmCircuitBuilder circuit_builder = generate_avm_circuit(); AvmComposer composer = AvmComposer(); - AvmProver prover = composer.create_prover(circuit_builder); - AvmVerifier verifier = composer.create_verifier(circuit_builder); + InnerProver prover = composer.create_prover(circuit_builder); + InnerVerifier verifier = composer.create_verifier(circuit_builder); HonkProof proof = prover.construct_proof(); @@ -83,12 +82,15 @@ TEST_F(AvmRecursiveTests, recursion) OuterBuilder outer_circuit; RecursiveVerifier recursive_verifier{ &outer_circuit, verification_key }; - auto pairing_points = recursive_verifier.verify_proof(proof); + auto agg_object = + stdlib::recursion::init_default_aggregation_state(outer_circuit); - bool pairing_points_valid = verification_key->pcs_verification_key->pairing_check(pairing_points[0].get_value(), - pairing_points[1].get_value()); + auto agg_output = recursive_verifier.verify_proof(proof, agg_object); - ASSERT_TRUE(pairing_points_valid) << "Pairing points are not valid."; + bool agg_output_valid = + verification_key->pcs_verification_key->pairing_check(agg_output.P0.get_value(), agg_output.P1.get_value()); + + ASSERT_TRUE(agg_output_valid) << "Pairing points (aggregation state) are not valid."; vinfo("Recursive verifier: num gates = ", outer_circuit.num_gates); ASSERT_FALSE(outer_circuit.failed()) << "Outer circuit has failed."; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp index f9c74ba7e6e..ea204252647 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp @@ -8,12 +8,10 @@ #include namespace tests_avm { - using namespace bb; using namespace bb::avm_trace; namespace { - void common_validate_arithmetic_op(Row const& main_row, Row const& alu_row, FF const& a, @@ -221,8 +219,8 @@ class AvmArithmeticTests : public ::testing::Test { } // Generate a trace with an EQ opcode operation. - std::vector gen_trace_eq(uint128_t const& a, - uint128_t const& b, + std::vector gen_trace_eq(uint256_t const& a, + uint256_t const& b, uint32_t const& addr_a, uint32_t const& addr_b, uint32_t const& addr_c, @@ -240,8 +238,8 @@ class AvmArithmeticTests : public ::testing::Test { // and the memory and alu trace are created consistently with the wrong value c_mutated. std::vector gen_mutated_trace_add(FF const& a, FF const& b, FF const& c_mutated, avm_trace::AvmMemoryTag tag) { - trace_builder.op_set(0, uint128_t{ a }, 0, tag); - trace_builder.op_set(0, uint128_t{ b }, 1, tag); + trace_builder.op_set(0, a, 0, tag); + trace_builder.op_set(0, b, 1, tag); trace_builder.op_add(0, 0, 1, 2, tag); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -257,8 +255,8 @@ class AvmArithmeticTests : public ::testing::Test { // and the memory and alu trace are created consistently with the wrong value c_mutated. std::vector gen_mutated_trace_sub(FF const& a, FF const& b, FF const& c_mutated, avm_trace::AvmMemoryTag tag) { - trace_builder.op_set(0, uint128_t{ a }, 0, tag); - trace_builder.op_set(0, uint128_t{ b }, 1, tag); + trace_builder.op_set(0, a, 0, tag); + trace_builder.op_set(0, b, 1, tag); trace_builder.op_sub(0, 0, 1, 2, tag); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -274,8 +272,8 @@ class AvmArithmeticTests : public ::testing::Test { // and the memory and alu trace are created consistently with the wrong value c_mutated. std::vector gen_mutated_trace_mul(FF const& a, FF const& b, FF const& c_mutated, avm_trace::AvmMemoryTag tag) { - trace_builder.op_set(0, uint128_t{ a }, 0, tag); - trace_builder.op_set(0, uint128_t{ b }, 1, tag); + trace_builder.op_set(0, a, 0, tag); + trace_builder.op_set(0, b, 1, tag); trace_builder.op_mul(0, 0, 1, 2, tag); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -294,8 +292,8 @@ class AvmArithmeticTests : public ::testing::Test { std::vector gen_mutated_trace_eq( FF const& a, FF const& b, FF const& c_mutated, FF const& mutated_inv_diff, avm_trace::AvmMemoryTag tag) { - trace_builder.op_set(0, uint128_t{ a }, 0, tag); - trace_builder.op_set(0, uint128_t{ b }, 1, tag); + trace_builder.op_set(0, a, 0, tag); + trace_builder.op_set(0, b, 1, tag); trace_builder.op_eq(0, 0, 1, 2, tag); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -393,7 +391,9 @@ TEST_F(AvmArithmeticTestsFF, addition) { std::vector const calldata = { 37, 4, 11 }; gen_trace_builder(calldata); - trace_builder.op_calldata_copy(0, 0, 3, 0); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); + trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [37,4,11,0,0,0,....] trace_builder.op_add(0, 0, 1, 4, AvmMemoryTag::FF); // [37,4,11,0,41,0,....] @@ -415,7 +415,9 @@ TEST_F(AvmArithmeticTestsFF, subtraction) { std::vector const calldata = { 8, 4, 17 }; gen_trace_builder(calldata); - trace_builder.op_calldata_copy(0, 0, 3, 0); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); + trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [8,4,17,0,0,0,....] trace_builder.op_sub(0, 2, 0, 1, AvmMemoryTag::FF); // [8,9,17,0,0,0....] @@ -436,7 +438,9 @@ TEST_F(AvmArithmeticTestsFF, multiplication) { std::vector const calldata = { 5, 0, 20 }; gen_trace_builder(calldata); - trace_builder.op_calldata_copy(0, 0, 3, 0); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); + trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [5,0,20,0,0,0,....] trace_builder.op_mul(0, 2, 0, 1, AvmMemoryTag::FF); // [5,100,20,0,0,0....] @@ -456,8 +460,10 @@ TEST_F(AvmArithmeticTestsFF, multiplication) // Test on multiplication by zero over finite field type. TEST_F(AvmArithmeticTestsFF, multiplicationByZero) { - std::vector const calldata = { 127 }; + std::vector const calldata = { 127, 0, 0 }; gen_trace_builder(calldata); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); + trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [127,0,0,0,0,0,....] @@ -480,10 +486,12 @@ TEST_F(AvmArithmeticTestsFF, fDivision) { std::vector const calldata = { 15, 315 }; gen_trace_builder(calldata); - trace_builder.op_calldata_copy(0, 0, 2, 0); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); + trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,315,0,0,0,0,....] - trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] + trace_builder.op_fdiv(0, 1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); @@ -504,12 +512,14 @@ TEST_F(AvmArithmeticTestsFF, fDivision) // Test on division with zero numerator over finite field type. TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) { - std::vector const calldata = { 15 }; + std::vector const calldata = { 15, 0, 0 }; gen_trace_builder(calldata); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); + trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] - trace_builder.op_fdiv(0, 1, 0, 0); // [0,0,0,0,0,0....] + trace_builder.op_fdiv(0, 1, 0, 0, AvmMemoryTag::FF); // [0,0,0,0,0,0....] trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); @@ -531,12 +541,14 @@ TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) // We check that the operator error flag is raised. TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) { - std::vector const calldata = { 15 }; + std::vector const calldata = { 15, 0, 0 }; gen_trace_builder(calldata); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); + trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] - trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] + trace_builder.op_fdiv(0, 0, 1, 2, AvmMemoryTag::FF); // [15,0,0,0,0,0....] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -559,7 +571,7 @@ TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) TEST_F(AvmArithmeticTestsFF, fDivisionZeroByZeroError) { // Memory layout: [0,0,0,0,0,0,....] - trace_builder.op_fdiv(0, 0, 1, 2); // [0,0,0,0,0,0....] + trace_builder.op_fdiv(0, 0, 1, 2, AvmMemoryTag::FF); // [0,0,0,0,0,0....] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -585,18 +597,21 @@ TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) { std::vector const calldata = { 45, 23, 12 }; gen_trace_builder(calldata); - trace_builder.op_calldata_copy(0, 0, 3, 2); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); + trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [0,0,45,23,12,0,0,0,....] - trace_builder.op_add(0, 2, 3, 4, AvmMemoryTag::FF); // [0,0,45,23,68,0,0,0,....] - trace_builder.op_add(0, 4, 5, 5, AvmMemoryTag::FF); // [0,0,45,23,68,68,0,0,....] - trace_builder.op_add(0, 5, 5, 5, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,0,....] - trace_builder.op_add(0, 5, 6, 7, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,0....] - trace_builder.op_sub(0, 7, 6, 8, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,136,0....] - trace_builder.op_mul(0, 8, 8, 8, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,136^2,0....] - trace_builder.op_fdiv(0, 3, 5, 1); // [0,23*136^(-1),45,23,68,136,0,136,136^2,0....] - trace_builder.op_fdiv(0, 1, 1, 9); // [0,23*136^(-1),45,23,68,136,0,136,136^2,1,0....] - trace_builder.op_fdiv(0, 9, 0, 4); // [0,23*136^(-1),45,23,1/0,136,0,136,136^2,1,0....] Error: division by 0 + trace_builder.op_add(0, 2, 3, 4, AvmMemoryTag::FF); // [0,0,45,23,68,0,0,0,....] + trace_builder.op_add(0, 4, 5, 5, AvmMemoryTag::FF); // [0,0,45,23,68,68,0,0,....] + trace_builder.op_add(0, 5, 5, 5, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,0,....] + trace_builder.op_add(0, 5, 6, 7, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,0....] + trace_builder.op_sub(0, 7, 6, 8, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,136,0....] + trace_builder.op_mul(0, 8, 8, 8, AvmMemoryTag::FF); // [0,0,45,23,68,136,0,136,136^2,0....] + trace_builder.op_fdiv(0, 3, 5, 1, AvmMemoryTag::FF); // [0,23*136^(-1),45,23,68,136,0,136,136^2,0....] + trace_builder.op_fdiv(0, 1, 1, 9, AvmMemoryTag::FF); // [0,23*136^(-1),45,23,68,136,0,136,136^2,1,0....] + trace_builder.op_fdiv( + 0, 9, 0, 4, AvmMemoryTag::FF); // [0,23*136^(-1),45,23,1/0,136,0,136,136^2,1,0....] Error: division by 0 trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -610,7 +625,9 @@ TEST_F(AvmArithmeticTestsFF, equality) FF elem = FF::modulus - FF(1); std::vector const calldata = { elem, elem }; gen_trace_builder(calldata); - trace_builder.op_calldata_copy(0, 0, 2, 0); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); + trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q - 1, 1, 0..] trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); @@ -631,7 +648,10 @@ TEST_F(AvmArithmeticTestsFF, nonEquality) FF elem = FF::modulus - FF(1); std::vector const calldata = { elem, elem + FF(1) }; gen_trace_builder(calldata); - trace_builder.op_calldata_copy(0, 0, 2, 0); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); + trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 0); + trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q, 0, 0..] trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); @@ -650,8 +670,8 @@ TEST_P(AvmArithmeticTestsDiv, division) { const auto [operands, mem_tag] = GetParam(); const auto [a, b, output] = operands; - trace_builder.op_set(0, uint128_t(a), 0, mem_tag); - trace_builder.op_set(0, uint128_t(b), 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_div(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -1056,7 +1076,7 @@ TEST_F(AvmArithmeticTestsU32, subtractionCarry) { // trace_builder trace_builder.op_set(0, UINT32_MAX - 99, 8, AvmMemoryTag::U32); - trace_builder.op_set(0, 3210987654, 9, AvmMemoryTag::U32); + trace_builder.op_set(0, uint256_t(3210987654), 9, AvmMemoryTag::U32); trace_builder.op_sub(0, 9, 8, 0, AvmMemoryTag::U32); trace_builder.op_return(0, 0, 0); @@ -1314,9 +1334,9 @@ TEST_F(AvmArithmeticTestsU64, nonEquality) // Test on basic addition over u128 type. TEST_F(AvmArithmeticTestsU128, addition) { - uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; - uint128_t const b = (uint128_t{ 0x3333222233331111LLU } << 64) + uint128_t{ 0x5555111155553333LLU }; - uint128_t const c = (uint128_t{ 0x8888444466665555LLU } << 64) + uint128_t{ 0xDDDDAAAAFFFFEEEELLU }; + const FF a = (uint256_t{ 0x5555222233334444LLU } << 64) + uint256_t{ 0x88889999AAAABBBBLLU }; + const FF b = (uint256_t{ 0x3333222233331111LLU } << 64) + uint256_t{ 0x5555111155553333LLU }; + const FF c = (uint256_t{ 0x8888444466665555LLU } << 64) + uint256_t{ 0xDDDDAAAAFFFFEEEELLU }; // trace_builder trace_builder.op_set(0, a, 8, AvmMemoryTag::U128); @@ -1326,14 +1346,7 @@ TEST_F(AvmArithmeticTestsU128, addition) trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); - auto alu_row = common_validate_add(trace, - FF(uint256_t::from_uint128(a)), - FF(uint256_t::from_uint128(b)), - FF(uint256_t::from_uint128(c)), - FF(8), - FF(9), - FF(9), - AvmMemoryTag::U128); + auto alu_row = common_validate_add(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); EXPECT_EQ(alu_row.alu_u128_tag, FF(1)); EXPECT_EQ(alu_row.alu_cf, FF(0)); @@ -1344,10 +1357,10 @@ TEST_F(AvmArithmeticTestsU128, addition) // Test on basic addition over u128 type with carry. TEST_F(AvmArithmeticTestsU128, additionCarry) { - uint128_t const a = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX } - uint128_t{ 72948899 }; - uint128_t const b = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX } - uint128_t{ 36177344 }; - uint128_t const c = - (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX } - uint128_t{ 36177345 } - uint128_t{ 72948899 }; + const FF a = (uint256_t{ UINT64_MAX } << 64) + uint256_t{ UINT64_MAX } - uint256_t{ 72948899 }; + const FF b = (uint256_t{ UINT64_MAX } << 64) + uint256_t{ UINT64_MAX } - uint256_t{ 36177344 }; + const FF c = + (uint256_t{ UINT64_MAX } << 64) + uint256_t{ UINT64_MAX } - uint256_t{ 36177345 } - uint256_t{ 72948899 }; // trace_builder trace_builder.op_set(0, a, 8, AvmMemoryTag::U128); @@ -1357,14 +1370,7 @@ TEST_F(AvmArithmeticTestsU128, additionCarry) trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); - auto alu_row = common_validate_add(trace, - FF(uint256_t::from_uint128(a)), - FF(uint256_t::from_uint128(b)), - FF(uint256_t::from_uint128(c)), - FF(8), - FF(9), - FF(9), - AvmMemoryTag::U128); + auto alu_row = common_validate_add(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); EXPECT_EQ(alu_row.alu_u128_tag, FF(1)); EXPECT_EQ(alu_row.alu_cf, FF(1)); @@ -1375,9 +1381,9 @@ TEST_F(AvmArithmeticTestsU128, additionCarry) // Test on basic subtraction over u128 type. TEST_F(AvmArithmeticTestsU128, subtraction) { - uint128_t const a = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX } - uint128_t{ 36177344 }; - uint128_t const b = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX } - uint128_t{ 72948899 }; - uint128_t const c = 36771555; // 72948899 - 36177344 + const FF a = (uint256_t{ UINT64_MAX } << 64) + uint256_t{ UINT64_MAX } - uint256_t{ 36177344 }; + const FF b = (uint256_t{ UINT64_MAX } << 64) + uint256_t{ UINT64_MAX } - uint256_t{ 72948899 }; + const FF c = 36771555; // 72948899 - 36177344 // trace_builder trace_builder.op_set(0, a, 8, AvmMemoryTag::U128); @@ -1387,14 +1393,7 @@ TEST_F(AvmArithmeticTestsU128, subtraction) trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); - auto alu_row = common_validate_sub(trace, - FF(uint256_t::from_uint128(a)), - FF(uint256_t::from_uint128(b)), - FF(uint256_t::from_uint128(c)), - FF(8), - FF(9), - FF(9), - AvmMemoryTag::U128); + auto alu_row = common_validate_sub(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); EXPECT_EQ(alu_row.alu_u128_tag, FF(1)); EXPECT_EQ(alu_row.alu_cf, FF(0)); @@ -1405,9 +1404,9 @@ TEST_F(AvmArithmeticTestsU128, subtraction) // Test on basic subtraction over u128 type with carry. TEST_F(AvmArithmeticTestsU128, subtractionCarry) { - uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; - uint128_t const b = (uint128_t{ 0x3333222233331111LLU } << 64) + uint128_t{ 0x5555111155553333LLU }; - uint128_t const c = (uint128_t{ 0x2222000000003333LLU } << 64) + uint128_t{ 0x3333888855558888LLU }; + const FF a = (uint256_t{ 0x5555222233334444LLU } << 64) + uint256_t{ 0x88889999AAAABBBBLLU }; + const FF b = (uint256_t{ 0x3333222233331111LLU } << 64) + uint256_t{ 0x5555111155553333LLU }; + const FF c = (uint256_t{ 0x2222000000003333LLU } << 64) + uint256_t{ 0x3333888855558888LLU }; // trace_builder trace_builder.op_set(0, a, 8, AvmMemoryTag::U128); @@ -1417,14 +1416,7 @@ TEST_F(AvmArithmeticTestsU128, subtractionCarry) trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); - auto alu_row = common_validate_sub(trace, - FF(uint256_t::from_uint128(a)), - FF(uint256_t::from_uint128(b)), - FF(uint256_t::from_uint128(c)), - FF(8), - FF(9), - FF(9), - AvmMemoryTag::U128); + auto alu_row = common_validate_sub(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); EXPECT_EQ(alu_row.alu_u128_tag, FF(1)); EXPECT_EQ(alu_row.alu_cf, FF(0)); @@ -1459,8 +1451,8 @@ TEST_F(AvmArithmeticTestsU128, multiplicationOverflow) { // (2^128 - 2) * (2^128 - 4) = 2^256 - 2^130 - 2^129 + 2^3 // The above modulo 2^128 = 8 - uint128_t const a = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX - 1 }; - uint128_t const b = (uint128_t{ UINT64_MAX } << 64) + uint128_t{ UINT64_MAX - 3 }; + const FF a = (uint256_t{ UINT64_MAX } << 64) + uint256_t{ UINT64_MAX - 1 }; + const FF b = (uint256_t{ UINT64_MAX } << 64) + uint256_t{ UINT64_MAX - 3 }; // trace_builder trace_builder.op_set(0, a, 0, AvmMemoryTag::U128); @@ -1470,14 +1462,7 @@ TEST_F(AvmArithmeticTestsU128, multiplicationOverflow) trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); - auto alu_row_index = common_validate_mul(trace, - FF{ uint256_t::from_uint128(a) }, - FF{ uint256_t::from_uint128(b) }, - FF{ 8 }, - FF(0), - FF(1), - FF(2), - AvmMemoryTag::U128); + auto alu_row_index = common_validate_mul(trace, a, b, FF{ 8 }, FF(0), FF(1), FF(2), AvmMemoryTag::U128); auto alu_row_first = trace.at(alu_row_index); EXPECT_EQ(alu_row_first.alu_u128_tag, FF(1)); @@ -1487,17 +1472,10 @@ TEST_F(AvmArithmeticTestsU128, multiplicationOverflow) TEST_F(AvmArithmeticTestsU128, equality) { - uint128_t const elem = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; + const FF elem = (uint256_t{ 0x5555222233334444LLU } << 64) + uint256_t{ 0x88889999AAAABBBBLLU }; auto trace = gen_trace_eq(elem, elem, 0, 1, 2, AvmMemoryTag::U128); - auto alu_row_index = common_validate_eq(trace, - FF(uint256_t::from_uint128(elem)), - FF(uint256_t::from_uint128(elem)), - FF(1), - FF(0), - FF(1), - FF(2), - AvmMemoryTag::U128); + auto alu_row_index = common_validate_eq(trace, elem, elem, FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::U128); auto alu_row = trace.at(alu_row_index); EXPECT_EQ(alu_row.alu_u128_tag, FF(1)); @@ -1508,18 +1486,11 @@ TEST_F(AvmArithmeticTestsU128, equality) // Test correct non-equality of U128 elements TEST_F(AvmArithmeticTestsU128, nonEquality) { - uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; - uint128_t const b = a - (0xdeadbeefLLU << 32); + const FF a = (uint256_t{ 0x5555222233334444LLU } << 64) + uint256_t{ 0x88889999AAAABBBBLLU }; + const FF b = a - (0xdeadbeefLLU << 32); auto trace = gen_trace_eq(a, b, 0, 1, 2, AvmMemoryTag::U128); - auto alu_row_index = common_validate_eq(trace, - FF(uint256_t::from_uint128(a)), - FF(uint256_t::from_uint128(b)), - FF(0), - FF(0), - FF(1), - FF(2), - AvmMemoryTag::U128); + auto alu_row_index = common_validate_eq(trace, a, b, FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U128); auto alu_row = trace.at(alu_row_index); EXPECT_EQ(alu_row.alu_u128_tag, FF(1)); @@ -1555,7 +1526,6 @@ TEST_F(AvmArithmeticTestsU128, nonEquality) // Test on basic incorrect addition over finite field type. TEST_F(AvmArithmeticNegativeTestsFF, addition) { - auto trace = gen_mutated_trace_add(FF(37), FF(4), FF(40), AvmMemoryTag::FF); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_ADD_SUB_1"); } @@ -1563,7 +1533,6 @@ TEST_F(AvmArithmeticNegativeTestsFF, addition) // Test on basic incorrect subtraction over finite field type. TEST_F(AvmArithmeticNegativeTestsFF, subtraction) { - auto trace = gen_mutated_trace_sub(FF(17), FF(8), FF(-9), AvmMemoryTag::FF); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_ADD_SUB_1"); } @@ -1571,7 +1540,6 @@ TEST_F(AvmArithmeticNegativeTestsFF, subtraction) // Test on basic incorrect multiplication over finite field type. TEST_F(AvmArithmeticNegativeTestsFF, multiplication) { - auto trace = gen_mutated_trace_mul(FF(9), FF(100), FF(9000000), AvmMemoryTag::FF); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_MULTIPLICATION_FF"); } @@ -1579,13 +1547,12 @@ TEST_F(AvmArithmeticNegativeTestsFF, multiplication) // Test on basic incorrect division over finite field type. TEST_F(AvmArithmeticNegativeTestsFF, fDivision) { - std::vector const calldata = { 15, 315 }; gen_trace_builder(calldata); trace_builder.op_calldata_copy(0, 0, 2, 0); // Memory layout: [15,315,0,0,0,0,....] - trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] + trace_builder.op_fdiv(0, 1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -1599,13 +1566,12 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivision) // in the trace. TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) { - std::vector const calldata = { 15, 315 }; gen_trace_builder(calldata); trace_builder.op_calldata_copy(0, 0, 2, 0); // Memory layout: [15,315,0,0,0,0,....] - trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] + trace_builder.op_fdiv(0, 1, 0, 2, AvmMemoryTag::FF); // [15,315,21,0,0,0....] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -1628,13 +1594,12 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) // Test with finite field division by zero occurs and no error is raised (remove error flag) TEST_F(AvmArithmeticNegativeTestsFF, fDivisionByZeroNoError) { - std::vector const calldata = { 15 }; gen_trace_builder(calldata); trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] - trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] + trace_builder.op_fdiv(0, 0, 1, 2, AvmMemoryTag::FF); // [15,0,0,0,0,0....] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -1650,9 +1615,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionByZeroNoError) // Test with finite field division of zero by zero occurs and no error is raised (remove error flag) TEST_F(AvmArithmeticNegativeTestsFF, fDivisionZeroByZeroNoError) { - // Memory layout: [0,0,0,0,0,0,....] - trace_builder.op_fdiv(0, 0, 1, 2); // [0,0,0,0,0,0....] + trace_builder.op_fdiv(0, 0, 1, 2, AvmMemoryTag::FF); // [0,0,0,0,0,0....] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -1668,12 +1632,11 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionZeroByZeroNoError) // Test with finite field division using a wrong read instruction tag TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongRInTag) { - std::vector const calldata = { 18, 6 }; gen_trace_builder(calldata); trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] - trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] + trace_builder.op_fdiv(0, 0, 1, 2, AvmMemoryTag::FF); // [18,6,3,0,0,0....] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -1689,12 +1652,11 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongRInTag) // Test with finite field division using a wrong write instruction tag TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) { - std::vector const calldata = { 18, 6 }; gen_trace_builder(calldata); trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] - trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] + trace_builder.op_fdiv(0, 0, 1, 2, AvmMemoryTag::FF); // [18,6,3,0,0,0....] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -1711,7 +1673,6 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) // the addition, subtraction, multiplication. TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag1) { - std::vector const calldata = { 37, 4, 11 }; gen_trace_builder(calldata); trace_builder.op_calldata_copy(0, 0, 3, 0); @@ -1733,7 +1694,6 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag1) TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag2) { - std::vector const calldata = { 8, 4, 17 }; gen_trace_builder(calldata); trace_builder.op_calldata_copy(0, 0, 3, 0); @@ -1754,7 +1714,6 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag2) TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag3) { - std::vector const calldata = { 5, 0, 20 }; gen_trace_builder(calldata); trace_builder.op_calldata_copy(0, 0, 3, 0); @@ -1776,7 +1735,6 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag3) // Tests a situation for field elements where a != b but c == 1; TEST_F(AvmArithmeticNegativeTestsFF, invalidEquality) { - std::vector trace = gen_mutated_trace_eq(FF::modulus_minus_two, FF(0), FF(1), FF(0), AvmMemoryTag::FF); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); } @@ -1784,7 +1742,6 @@ TEST_F(AvmArithmeticNegativeTestsFF, invalidEquality) // Tests a situation for field elements where a == b but c == 0; TEST_F(AvmArithmeticNegativeTestsFF, invalidInequality) { - std::vector trace = gen_mutated_trace_eq(FF::modulus_minus_two, FF::modulus_minus_two, FF(0), FF(0), AvmMemoryTag::FF); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); @@ -1793,7 +1750,6 @@ TEST_F(AvmArithmeticNegativeTestsFF, invalidInequality) // Tests a situation for field elements where c is non-boolean, i,e, c!= {0,1}; TEST_F(AvmArithmeticNegativeTestsFF, nonBooleanEq) { - std::vector trace = gen_mutated_trace_eq(FF::modulus_minus_two, FF::modulus_minus_two, FF(10), FF(0), AvmMemoryTag::FF); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_RES_IS_BOOL"); @@ -1802,7 +1758,6 @@ TEST_F(AvmArithmeticNegativeTestsFF, nonBooleanEq) // Tests a situation for field elements where the tag for c is not U8. TEST_F(AvmArithmeticNegativeTestsFF, eqOutputWrongTag) { - FF elem = FF::modulus - FF(15); std::vector const calldata = { elem, elem }; gen_trace_builder(calldata); @@ -1822,7 +1777,6 @@ TEST_F(AvmArithmeticNegativeTestsFF, eqOutputWrongTag) // Tests a situation for field elements the (a-b)^1 is incorrect. i.e. (a-b) * (a-b)^1 != 1 for (a-b) != 0; TEST_F(AvmArithmeticNegativeTestsFF, invalidInverseDifference) { - // The a, b and c registers contain the correct information, only the inversion of differences is wrong. std::vector trace = gen_mutated_trace_eq(FF::modulus_minus_two, FF(0), FF(0), FF(5).invert(), AvmMemoryTag::FF); @@ -1836,7 +1790,6 @@ TEST_F(AvmArithmeticNegativeTestsFF, invalidInverseDifference) // Test on basic incorrect addition over U8. TEST_F(AvmArithmeticNegativeTestsU8, addition) { - auto trace = gen_mutated_trace_add(FF(234), FF(22), FF(1), AvmMemoryTag::U8); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_ADD_SUB_2"); } @@ -1844,7 +1797,6 @@ TEST_F(AvmArithmeticNegativeTestsU8, addition) // Test on basic incorrect subtraction over U8. TEST_F(AvmArithmeticNegativeTestsU8, subtraction) { - auto trace = gen_mutated_trace_sub(FF(100), FF(104), FF(253), AvmMemoryTag::U8); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_ADD_SUB_2"); } @@ -1852,7 +1804,6 @@ TEST_F(AvmArithmeticNegativeTestsU8, subtraction) // Test on basic incorrect multiplication over U8. TEST_F(AvmArithmeticNegativeTestsU8, multiplication) { - auto trace = gen_mutated_trace_mul(FF(9), FF(100), FF(55), AvmMemoryTag::U8); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_MUL_COMMON_2"); } @@ -1860,7 +1811,6 @@ TEST_F(AvmArithmeticNegativeTestsU8, multiplication) // Tests a situation for U8 elements where a != b but c == 1; TEST_F(AvmArithmeticNegativeTestsU8, invalidEquality) { - std::vector trace = gen_mutated_trace_eq(FF(10), FF(255), FF(1), FF(0), AvmMemoryTag::U8); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); } @@ -1868,7 +1818,6 @@ TEST_F(AvmArithmeticNegativeTestsU8, invalidEquality) // Tests a situation for U8 elements where a == b but c == 0; TEST_F(AvmArithmeticNegativeTestsU8, invalidInequality) { - std::vector trace = gen_mutated_trace_eq(FF(128), FF(128), FF(0), FF(0), AvmMemoryTag::U8); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); } @@ -1876,7 +1825,6 @@ TEST_F(AvmArithmeticNegativeTestsU8, invalidInequality) // Tests a situation for U8 elements where c is non-boolean, i,e, c!= {0,1}; TEST_F(AvmArithmeticNegativeTestsU8, nonBooleanEq) { - std::vector trace = gen_mutated_trace_eq(FF(128), FF(128), FF(200), FF(0), AvmMemoryTag::U8); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_RES_IS_BOOL"); } @@ -1884,7 +1832,6 @@ TEST_F(AvmArithmeticNegativeTestsU8, nonBooleanEq) // Tests a situation for U8 elements where the tag for c is not U8. TEST_F(AvmArithmeticNegativeTestsU8, eqOutputWrongTag) { - auto trace = gen_trace_eq(2, 3, 23, 24, 25, AvmMemoryTag::U8); // Find the first row enabling the eq selector @@ -1898,7 +1845,6 @@ TEST_F(AvmArithmeticNegativeTestsU8, eqOutputWrongTag) // Tests a situation for U8 elements the (a-b)^1 is incorrect. i.e. (a-b) * (a-b)^1 != 1 for (a-b) != 0; TEST_F(AvmArithmeticNegativeTestsU8, invalidInverseDifference) { - // The a, b and c registers contain the correct information, only the inversion of differences is wrong. std::vector trace = gen_mutated_trace_eq(FF(130), FF(0), FF(0), FF(1000).invert(), AvmMemoryTag::U8); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); @@ -1911,7 +1857,6 @@ TEST_F(AvmArithmeticNegativeTestsU8, invalidInverseDifference) // Test on basic incorrect addition over U16. TEST_F(AvmArithmeticNegativeTestsU16, addition) { - auto trace = gen_mutated_trace_add(FF(8234), FF(7428), FF(653), AvmMemoryTag::U16); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_ADD_SUB_2"); } @@ -1919,7 +1864,6 @@ TEST_F(AvmArithmeticNegativeTestsU16, addition) // Test on basic incorrect subtraction over U16. TEST_F(AvmArithmeticNegativeTestsU16, subtraction) { - auto trace = gen_mutated_trace_sub(FF(100), FF(932), FF(25373), AvmMemoryTag::U16); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_ADD_SUB_2"); } @@ -1927,7 +1871,6 @@ TEST_F(AvmArithmeticNegativeTestsU16, subtraction) // Test on basic incorrect multiplication over U16. TEST_F(AvmArithmeticNegativeTestsU16, multiplication) { - auto trace = gen_mutated_trace_mul(FF(8096), FF(1024), FF(1), AvmMemoryTag::U16); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_MUL_COMMON_2"); } @@ -1935,7 +1878,6 @@ TEST_F(AvmArithmeticNegativeTestsU16, multiplication) // Tests a situation for U16 elements where a != b but c == 1; TEST_F(AvmArithmeticNegativeTestsU16, invalidEquality) { - std::vector trace = gen_mutated_trace_eq(FF(10), FF(255), FF(1), FF(0), AvmMemoryTag::U16); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); } @@ -1943,7 +1885,6 @@ TEST_F(AvmArithmeticNegativeTestsU16, invalidEquality) // Tests a situation for U16 elements where a == b but c == 0; TEST_F(AvmArithmeticNegativeTestsU16, invalidInequality) { - std::vector trace = gen_mutated_trace_eq(FF(128), FF(128), FF(0), FF(0), AvmMemoryTag::U16); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); } @@ -1951,7 +1892,6 @@ TEST_F(AvmArithmeticNegativeTestsU16, invalidInequality) // Tests a situation for U16 elements where c is non-boolean, i,e, c!= {0,1}; TEST_F(AvmArithmeticNegativeTestsU16, nonBooleanEq) { - std::vector trace = gen_mutated_trace_eq(FF(128), FF(128), FF(200), FF(0), AvmMemoryTag::U16); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_RES_IS_BOOL"); } @@ -1959,7 +1899,6 @@ TEST_F(AvmArithmeticNegativeTestsU16, nonBooleanEq) // Tests a situation for U16 elements where the tag for c is not U8. TEST_F(AvmArithmeticNegativeTestsU16, eqOutputWrongTag) { - auto trace = gen_trace_eq(1515, 1515, 23, 24, 25, AvmMemoryTag::U16); // Find the first row enabling the eq selector @@ -1973,7 +1912,6 @@ TEST_F(AvmArithmeticNegativeTestsU16, eqOutputWrongTag) // Tests a situation for U16 elements the (a-b)^1 is incorrect. i.e. (a-b) * (a-b)^1 != 1 for (a-b) != 0; TEST_F(AvmArithmeticNegativeTestsU16, invalidInverseDifference) { - // The a, b and c registers contain the correct information, only the inversion of differences is wrong. std::vector trace = gen_mutated_trace_eq(FF(130), FF(0), FF(0), FF(1000).invert(), AvmMemoryTag::U16); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); @@ -1985,7 +1923,6 @@ TEST_F(AvmArithmeticNegativeTestsU16, invalidInverseDifference) // Test on basic incorrect addition over U32. TEST_F(AvmArithmeticNegativeTestsU32, addition) { - auto trace = gen_mutated_trace_add(FF(1972382341), FF(1111133221), FF(1222222222), AvmMemoryTag::U32); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_ADD_SUB_2"); } @@ -1993,7 +1930,6 @@ TEST_F(AvmArithmeticNegativeTestsU32, addition) // Test on basic incorrect subtraction over U32. TEST_F(AvmArithmeticNegativeTestsU32, subtraction) { - auto trace = gen_mutated_trace_sub(FF(3999888777LLU), FF(UINT32_MAX), FF(2537332433LLU), AvmMemoryTag::U32); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_ADD_SUB_2"); } @@ -2001,7 +1937,6 @@ TEST_F(AvmArithmeticNegativeTestsU32, subtraction) // Test on basic incorrect multiplication over U32. TEST_F(AvmArithmeticNegativeTestsU32, multiplication) { - auto trace = gen_mutated_trace_mul(FF(UINT32_MAX), FF(UINT32_MAX), FF(0), AvmMemoryTag::U32); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_MUL_COMMON_2"); } @@ -2009,7 +1944,6 @@ TEST_F(AvmArithmeticNegativeTestsU32, multiplication) // Tests a situation for U32 elements where a != b but c == 1; TEST_F(AvmArithmeticNegativeTestsU32, invalidEquality) { - std::vector trace = gen_mutated_trace_eq(FF(UINT32_MAX - 10), FF(UINT32_MAX), FF(1), FF(0), AvmMemoryTag::U32); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); } @@ -2017,7 +1951,6 @@ TEST_F(AvmArithmeticNegativeTestsU32, invalidEquality) // Tests a situation for U32 elements where a == b but c == 0; TEST_F(AvmArithmeticNegativeTestsU32, invalidInequality) { - std::vector trace = gen_mutated_trace_eq(FF(73934721LLU), FF(73934721LLU), FF(0), FF(0), AvmMemoryTag::U32); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); } @@ -2025,7 +1958,6 @@ TEST_F(AvmArithmeticNegativeTestsU32, invalidInequality) // Tests a situation for U32 elements where c is non-boolean, i,e, c!= {0,1}; TEST_F(AvmArithmeticNegativeTestsU32, nonBooleanEq) { - std::vector trace = gen_mutated_trace_eq(FF(623138LLU), FF(623138LLU), FF(8728342LLU), FF(0), AvmMemoryTag::U32); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_RES_IS_BOOL"); @@ -2034,7 +1966,6 @@ TEST_F(AvmArithmeticNegativeTestsU32, nonBooleanEq) // Tests a situation for U32 elements where the tag for c is not U8. TEST_F(AvmArithmeticNegativeTestsU32, eqOutputWrongTag) { - auto trace = gen_trace_eq(15, 15, 23, 24, 25, AvmMemoryTag::U32); // Find the first row enabling the eq selector @@ -2048,7 +1979,6 @@ TEST_F(AvmArithmeticNegativeTestsU32, eqOutputWrongTag) // Tests a situation for U32 elements the (a-b)^1 is incorrect. i.e. (a-b) * (a-b)^1 != 1 for (a-b) != 0; TEST_F(AvmArithmeticNegativeTestsU32, invalidInverseDifference) { - // The a, b and c registers contain the correct information, only the inversion of differences is wrong. std::vector trace = gen_mutated_trace_eq(FF(74329231LLU), FF(74329231LLU), FF(0), FF(7432701LLU).invert(), AvmMemoryTag::U32); @@ -2062,7 +1992,6 @@ TEST_F(AvmArithmeticNegativeTestsU32, invalidInverseDifference) // Test on basic incorrect addition over U64. TEST_F(AvmArithmeticNegativeTestsU64, addition) { - auto trace = gen_mutated_trace_add( FF(3324236423198282341LLU), FF(999999991111133221LLU), FF(1222222222236LLU), AvmMemoryTag::U64); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_ADD_SUB_2"); @@ -2071,7 +2000,6 @@ TEST_F(AvmArithmeticNegativeTestsU64, addition) // Test on basic incorrect subtraction over U64. TEST_F(AvmArithmeticNegativeTestsU64, subtraction) { - auto trace = gen_mutated_trace_sub(FF(399988877723434LLU), FF(UINT64_MAX), FF(25373324332342LLU), AvmMemoryTag::U64); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_ADD_SUB_2"); @@ -2080,7 +2008,6 @@ TEST_F(AvmArithmeticNegativeTestsU64, subtraction) // Test on basic incorrect multiplication over U64. TEST_F(AvmArithmeticNegativeTestsU64, multiplication) { - auto trace = gen_mutated_trace_mul(FF(399988877723434LLU), FF(9998887772343LLU), FF(9283674827534LLU), AvmMemoryTag::U64); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_MUL_COMMON_2"); @@ -2089,7 +2016,6 @@ TEST_F(AvmArithmeticNegativeTestsU64, multiplication) // Tests a situation for U64 elements where a != b but c == 1; TEST_F(AvmArithmeticNegativeTestsU64, invalidEquality) { - std::vector trace = gen_mutated_trace_eq(FF(3999888777231234LLU), FF(3999882177231234LLU), FF(1), FF(0), AvmMemoryTag::U64); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); @@ -2098,7 +2024,6 @@ TEST_F(AvmArithmeticNegativeTestsU64, invalidEquality) // Tests a situation for U64 elements where a == b but c == 0; TEST_F(AvmArithmeticNegativeTestsU64, invalidInequality) { - std::vector trace = gen_mutated_trace_eq(FF(9998887772343LLU), FF(73934721LLU), FF(0), FF(0), AvmMemoryTag::U64); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_OP_EQ"); @@ -2107,7 +2032,6 @@ TEST_F(AvmArithmeticNegativeTestsU64, invalidInequality) // Tests a situation for U64 elements where c is non-boolean, i,e, c!= {0,1}; TEST_F(AvmArithmeticNegativeTestsU64, nonBooleanEq) { - std::vector trace = gen_mutated_trace_eq(FF(9998887772343LLU), FF(9998887772343LLU), FF(2), FF(0), AvmMemoryTag::U64); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "ALU_RES_IS_BOOL"); @@ -2116,7 +2040,6 @@ TEST_F(AvmArithmeticNegativeTestsU64, nonBooleanEq) // Tests a situation for U64 elements where the tag for c is not U8. TEST_F(AvmArithmeticNegativeTestsU64, eqOutputWrongTag) { - auto trace = gen_trace_eq(198732, 15, 23, 24, 25, AvmMemoryTag::U64); // Find the first row enabling the eq selector @@ -2130,7 +2053,6 @@ TEST_F(AvmArithmeticNegativeTestsU64, eqOutputWrongTag) // Tests a situation for U64 elements the (a-b)^1 is incorrect. i.e. (a-b) * (a-b)^1 != 1 for (a-b) != 0; TEST_F(AvmArithmeticNegativeTestsU64, invalidInverseDifference) { - // The a, b and c registers contain the correct information, only the inversion of differences is wrong. std::vector trace = gen_mutated_trace_eq( FF(9998887772343LLU), FF(9998887772343LLU), FF(0), FF(0x373428).invert(), AvmMemoryTag::U64); @@ -2144,7 +2066,6 @@ TEST_F(AvmArithmeticNegativeTestsU64, invalidInverseDifference) // Test on basic incorrect addition over U128. TEST_F(AvmArithmeticNegativeTestsU128, addition) { - uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; uint128_t const b = (uint128_t{ 0x3333222233331111LLU } << 64) + uint128_t{ 0x5555111155553333LLU }; uint128_t const c = (uint128_t{ 0x8888444466665555LLU } << 64) + uint128_t{ 0xDDDDAAAAFFFFEEEFLLU }; @@ -2159,7 +2080,6 @@ TEST_F(AvmArithmeticNegativeTestsU128, addition) // Test on basic incorrect subtraction over U128. TEST_F(AvmArithmeticNegativeTestsU128, subtraction) { - uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; uint128_t const b = (uint128_t{ 0x7333222233331111LLU } << 64) + uint128_t{ 0x5555111155553333LLU }; uint128_t const c = (uint128_t{ 0x8888444466665555LLU } << 64) + uint128_t{ 0xDDDDALLU }; @@ -2174,7 +2094,6 @@ TEST_F(AvmArithmeticNegativeTestsU128, subtraction) // Test on basic incorrect multiplication over U128. TEST_F(AvmArithmeticNegativeTestsU128, multiplication) { - uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; uint128_t const b = (uint128_t{ 0x7333222233331111LLU } << 64) + uint128_t{ 0x5555111155553333LLU }; uint128_t const c = (uint128_t{ 0x8888444466665555LLU } << 64) + uint128_t{ 0xDDDDALLU }; @@ -2190,7 +2109,6 @@ TEST_F(AvmArithmeticNegativeTestsU128, multiplication) // another alu operation. TEST_F(AvmArithmeticNegativeTestsU128, multiplicationSecondRowNoOp) { - trace_builder.op_set(0, 3, 0, AvmMemoryTag::U128); trace_builder.op_set(0, 4, 1, AvmMemoryTag::U128); @@ -2221,7 +2139,6 @@ TEST_F(AvmArithmeticNegativeTestsU128, multiplicationSecondRowNoOp) // Tests a situation for U128 elements where a != b but c == 1; TEST_F(AvmArithmeticNegativeTestsU128, invalidEquality) { - uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; FF const ff_a = FF{ uint256_t::from_uint128(a) }; uint128_t const b = (uint128_t{ 0x5555222313334444LLU } << 64) + uint128_t{ 0x88889998AAABBBBLLU }; @@ -2234,7 +2151,6 @@ TEST_F(AvmArithmeticNegativeTestsU128, invalidEquality) // Tests a situation for U128 elements where a == b but c == 0; TEST_F(AvmArithmeticNegativeTestsU128, invalidInequality) { - uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; FF const ff_a = FF{ uint256_t::from_uint128(a) }; @@ -2245,7 +2161,6 @@ TEST_F(AvmArithmeticNegativeTestsU128, invalidInequality) // Tests a situation for U128 elements where c is non-boolean, i,e, c!= {0,1}; TEST_F(AvmArithmeticNegativeTestsU128, nonBooleanEq) { - uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; FF const ff_a = FF{ uint256_t::from_uint128(a) }; std::vector trace = gen_mutated_trace_eq(ff_a, ff_a, FF::modulus - FF(1), FF(0), AvmMemoryTag::U128); @@ -2255,7 +2170,6 @@ TEST_F(AvmArithmeticNegativeTestsU128, nonBooleanEq) // Tests a situation for U128 elements where the tag for c is not U8. TEST_F(AvmArithmeticNegativeTestsU128, eqOutputWrongTag) { - auto trace = gen_trace_eq(1587, 1587, 23, 24, 25, AvmMemoryTag::U128); // Find the first row enabling the eq selector @@ -2269,7 +2183,6 @@ TEST_F(AvmArithmeticNegativeTestsU128, eqOutputWrongTag) // Tests a situation for U128 elements the (a-b)^1 is incorrect. i.e. (a-b) * (a-b)^1 != 1 for (a-b) != 0; TEST_F(AvmArithmeticNegativeTestsU128, invalidInverseDifference) { - uint128_t const a = (uint128_t{ 0x5555222233334444LLU } << 64) + uint128_t{ 0x88889999AAAABBBBLLU }; FF const ff_a = FF{ uint256_t::from_uint128(a) }; // The a, b and c registers contain the correct information, only the inversion of differences is wrong. diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp index deab35a0efc..ecb51b50a7d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp @@ -357,7 +357,7 @@ class AvmBitwiseTests : public ::testing::Test { std::vector gen_mutated_trace_not(FF const& a, FF const& c_mutated, avm_trace::AvmMemoryTag tag) { - trace_builder.op_set(0, uint128_t{ a }, 0, tag); + trace_builder.op_set(0, a, 0, tag); trace_builder.op_not(0, 0, 1, tag); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -375,21 +375,21 @@ class AvmBitwiseTests : public ::testing::Test { * ******************************************************************************/ -using TwoOpParamRow = std::tuple, AvmMemoryTag>; +using TwoOpParamRow = std::tuple, AvmMemoryTag>; std::vector mem_tags{ { AvmMemoryTag::U8, AvmMemoryTag::U16, AvmMemoryTag::U32, AvmMemoryTag::U64, AvmMemoryTag::U128 } }; -std::vector> positive_op_not_test_values = { { { 1, 254 }, - { 512, 65'023 }, - { 131'072, 4'294'836'223LLU }, - { 0x100000000LLU, 0xfffffffeffffffffLLU }, - { uint128_t{ 0x4000000000000 } << 64, - (uint128_t{ 0xfffbffffffffffff } << 64) + - uint128_t{ 0xffffffffffffffff } } } }; +std::vector> positive_op_not_test_values = { { { 1, 254 }, + { 512, 65'023 }, + { 131'072, 4'294'836'223LLU }, + { 0x100000000LLU, 0xfffffffeffffffffLLU }, + { uint256_t{ 0x4000000000000 } << 64, + (uint256_t{ 0xfffbffffffffffff } << 64) + + uint256_t{ 0xffffffffffffffff } } } }; // This is essentially a zip while we wait for C++23 -std::vector gen_two_op_params(std::vector> operands, +std::vector gen_two_op_params(std::vector> operands, std::vector mem_tags) { std::vector params; @@ -470,9 +470,7 @@ TEST_P(AvmBitwiseTestsNot, ParamTest) trace_builder.op_not(0, 0, 1, mem_tag); // [1,254,0,0,....] trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); - FF ff_a = FF(uint256_t::from_uint128(a)); - FF ff_output = FF(uint256_t::from_uint128(output)); - common_validate_op_not(trace, ff_a, ff_output, FF(0), FF(1), mem_tag); + common_validate_op_not(trace, a, output, FF(0), FF(1), mem_tag); validate_trace(std::move(trace), public_inputs); } @@ -484,8 +482,8 @@ TEST_P(AvmBitwiseTestsAnd, AllAndTest) { const auto [operands, mem_tag] = GetParam(); const auto [a, b, output] = operands; - trace_builder.op_set(0, uint128_t(a), 0, mem_tag); - trace_builder.op_set(0, uint128_t(b), 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_and(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 2, 1); @@ -501,8 +499,8 @@ TEST_P(AvmBitwiseTestsOr, AllOrTest) { const auto [operands, mem_tag] = GetParam(); const auto [a, b, output] = operands; - trace_builder.op_set(0, uint128_t(a), 0, mem_tag); - trace_builder.op_set(0, uint128_t(b), 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_or(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 2, 1); auto trace = trace_builder.finalize(); @@ -518,8 +516,8 @@ TEST_P(AvmBitwiseTestsXor, AllXorTest) { const auto [operands, mem_tag] = GetParam(); const auto [a, b, output] = operands; - trace_builder.op_set(0, uint128_t(a), 0, mem_tag); - trace_builder.op_set(0, uint128_t(b), 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_xor(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 2, 1); auto trace = trace_builder.finalize(); @@ -536,8 +534,8 @@ TEST_P(AvmBitwiseTestsShr, AllShrTest) { const auto [operands, mem_tag] = GetParam(); const auto [a, b, output] = operands; - trace_builder.op_set(0, uint128_t(a), 0, mem_tag); - trace_builder.op_set(0, uint128_t(b), 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_shr(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 2, 1); auto trace = trace_builder.finalize(); @@ -553,8 +551,8 @@ TEST_P(AvmBitwiseTestsShl, AllShlTest) { const auto [operands, mem_tag] = GetParam(); const auto [a, b, output] = operands; - trace_builder.op_set(0, uint128_t(a), 0, mem_tag); - trace_builder.op_set(0, uint128_t(b), 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_shl(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 2, 1); auto trace = trace_builder.finalize(); @@ -653,8 +651,8 @@ TEST_P(AvmBitwiseNegativeTestsAnd, AllNegativeTests) const auto [failure_string, failure_mode] = failure; const auto [operands, mem_tag] = params; const auto [a, b, output] = operands; - trace_builder.op_set(0, uint128_t{ a }, 0, mem_tag); - trace_builder.op_set(0, uint128_t{ b }, 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_and(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -672,8 +670,8 @@ TEST_P(AvmBitwiseNegativeTestsOr, AllNegativeTests) const auto [failure_string, failure_mode] = failure; const auto [operands, mem_tag] = params; const auto [a, b, output] = operands; - trace_builder.op_set(0, uint128_t{ a }, 0, mem_tag); - trace_builder.op_set(0, uint128_t{ b }, 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_or(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -690,8 +688,8 @@ TEST_P(AvmBitwiseNegativeTestsXor, AllNegativeTests) const auto [failure_string, failure_mode] = failure; const auto [operands, mem_tag] = params; const auto [a, b, output] = operands; - trace_builder.op_set(0, uint128_t{ a }, 0, mem_tag); - trace_builder.op_set(0, uint128_t{ b }, 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_xor(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -708,8 +706,8 @@ TEST_P(AvmBitwiseNegativeTestsShr, AllNegativeTests) const auto [failure, params] = GetParam(); const auto [operands, mem_tag] = params; const auto [a, b, output] = operands; - trace_builder.op_set(0, uint128_t{ a }, 0, mem_tag); - trace_builder.op_set(0, uint128_t{ b }, 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_shr(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -727,8 +725,8 @@ TEST_P(AvmBitwiseNegativeTestsShl, AllNegativeTests) const auto [failure, params] = GetParam(); const auto [operands, mem_tag] = params; const auto [a, b, output] = operands; - trace_builder.op_set(0, uint128_t{ a }, 0, mem_tag); - trace_builder.op_set(0, uint128_t{ b }, 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_shl(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp index cb34d2c48c0..b9985009ba3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp @@ -1,3 +1,4 @@ +#include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/vm/avm/tests/helpers.test.hpp" #include "barretenberg/vm/avm/trace/common.hpp" #include "common.test.hpp" @@ -33,7 +34,7 @@ class AvmCastTests : public ::testing::Test { void gen_trace( uint128_t const& a, uint32_t src_address, uint32_t dst_address, AvmMemoryTag src_tag, AvmMemoryTag dst_tag) { - trace_builder.op_set(0, a, src_address, src_tag); + trace_builder.op_set(0, uint256_t::from_uint128(a), src_address, src_tag); trace_builder.op_cast(0, src_address, dst_address, dst_tag); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -171,6 +172,7 @@ TEST_F(AvmCastTests, truncationFFToU16ModMinus1) { calldata = { FF::modulus - 1 }; trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_set(0, 1, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); @@ -184,6 +186,7 @@ TEST_F(AvmCastTests, truncationFFToU16ModMinus2) { calldata = { FF::modulus_minus_two }; trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_set(0, 1, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); trace_builder.op_return(0, 0, 0); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp index 36ec0f9bee9..b1315b0bb97 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp @@ -113,8 +113,8 @@ TEST_P(AvmCmpTestsLT, ParamTest) trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); trace_builder.op_calldata_copy(0, 0, 2, 0); } else { - trace_builder.op_set(0, uint128_t(a), 0, mem_tag); - trace_builder.op_set(0, uint128_t(b), 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); } trace_builder.op_lt(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 0, 0); @@ -149,8 +149,8 @@ TEST_P(AvmCmpTestsLTE, ParamTest) trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); trace_builder.op_calldata_copy(0, 0, 2, 0); } else { - trace_builder.op_set(0, uint128_t(a), 0, mem_tag); - trace_builder.op_set(0, uint128_t(b), 1, mem_tag); + trace_builder.op_set(0, a, 0, mem_tag); + trace_builder.op_set(0, b, 1, mem_tag); } trace_builder.op_lte(0, 0, 1, 2, mem_tag); trace_builder.op_return(0, 0, 0); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp index 8a776a123e9..00b53ce7d93 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp @@ -1,6 +1,7 @@ #include "barretenberg/vm/avm/trace/execution.hpp" #include +#include #include #include @@ -67,12 +68,12 @@ class AvmExecutionTests : public ::testing::Test { // Parsing, trace generation and proving is verified. TEST_F(AvmExecutionTests, basicAddReturn) { - std::string bytecode_hex = to_hex(OpCode::ADD) + // opcode ADD + std::string bytecode_hex = to_hex(OpCode::ADD_16) + // opcode ADD "00" // Indirect flag "01" // U8 - "00000007" // addr a 7 - "00000009" // addr b 9 - "00000001" // addr c 1 + "0007" // addr a 7 + "0009" // addr b 9 + "0001" // addr c 1 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "00000000" // ret offset 0 @@ -86,13 +87,13 @@ TEST_F(AvmExecutionTests, basicAddReturn) // ADD EXPECT_THAT(instructions.at(0), - AllOf(Field(&Instruction::op_code, OpCode::ADD), + AllOf(Field(&Instruction::op_code, OpCode::ADD_16), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(AvmMemoryTag::U8), - VariantWith(7), - VariantWith(9), - VariantWith(1))))); + VariantWith(7), + VariantWith(9), + VariantWith(1))))); // RETURN EXPECT_THAT(instructions.at(1), @@ -107,22 +108,22 @@ TEST_F(AvmExecutionTests, basicAddReturn) // Positive test for SET and SUB opcodes TEST_F(AvmExecutionTests, setAndSubOpcodes) { - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET + std::string bytecode_hex = to_hex(OpCode::SET_16) + // opcode SET "00" // Indirect flag "02" // U16 "B813" // val 47123 - "000000AA" // dst_offset 170 - + to_hex(OpCode::SET) + // opcode SET + "00AA" // dst_offset 170 + + to_hex(OpCode::SET_16) + // opcode SET "00" // Indirect flag "02" // U16 "9103" // val 37123 - "00000033" // dst_offset 51 - + to_hex(OpCode::SUB) + // opcode SUB + "0033" // dst_offset 51 + + to_hex(OpCode::SUB_8) + // opcode SUB "00" // Indirect flag "02" // U16 - "000000AA" // addr a - "00000033" // addr b - "00000001" // addr c 1 + "AA" // addr a + "33" // addr b + "01" // addr c 1 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "00000000" // ret offset 0 @@ -135,31 +136,31 @@ TEST_F(AvmExecutionTests, setAndSubOpcodes) // SET EXPECT_THAT(instructions.at(0), - AllOf(Field(&Instruction::op_code, OpCode::SET), + AllOf(Field(&Instruction::op_code, OpCode::SET_16), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(AvmMemoryTag::U16), VariantWith(47123), - VariantWith(170))))); + VariantWith(170))))); // SET EXPECT_THAT(instructions.at(1), - AllOf(Field(&Instruction::op_code, OpCode::SET), + AllOf(Field(&Instruction::op_code, OpCode::SET_16), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(AvmMemoryTag::U16), VariantWith(37123), - VariantWith(51))))); + VariantWith(51))))); // SUB EXPECT_THAT(instructions.at(2), - AllOf(Field(&Instruction::op_code, OpCode::SUB), + AllOf(Field(&Instruction::op_code, OpCode::SUB_8), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(AvmMemoryTag::U16), - VariantWith(170), - VariantWith(51), - VariantWith(1))))); + VariantWith(170), + VariantWith(51), + VariantWith(1))))); auto trace = gen_trace_from_instr(instructions); @@ -177,25 +178,23 @@ TEST_F(AvmExecutionTests, setAndSubOpcodes) // the result at offset 1. TEST_F(AvmExecutionTests, powerWithMulOpcodes) { - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET - "00" // Indirect flag - "04" // U64 - "00000000" // val 5 higher 32 bits - "00000005" // val 5 lower 32 bits - "00000000" // dst_offset 0 - + to_hex(OpCode::SET) + // opcode SET - "00" // Indirect flag - "04" // U64 - "00000000" // val 1 higher 32 bits - "00000001" // val 1 lower 32 bits - "00000001"; // dst_offset 1 - - std::string const mul_hex = to_hex(OpCode::MUL) + // opcode MUL - "00" // Indirect flag - "04" // U64 - "00000000" // addr a - "00000001" // addr b - "00000001"; // addr c 1 + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "04" // U64 + "05" // val + "00" // dst_offset 0 + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "04" // U64 + "01" // val + "01"; // dst_offset 1 + + std::string const mul_hex = to_hex(OpCode::MUL_8) + // opcode MUL + "00" // Indirect flag + "04" // U64 + "00" // addr a + "01" // addr b + "01"; // addr c 1 std::string const ret_hex = to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag @@ -215,23 +214,23 @@ TEST_F(AvmExecutionTests, powerWithMulOpcodes) // MUL first pos EXPECT_THAT(instructions.at(2), - AllOf(Field(&Instruction::op_code, OpCode::MUL), + AllOf(Field(&Instruction::op_code, OpCode::MUL_8), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(AvmMemoryTag::U64), - VariantWith(0), - VariantWith(1), - VariantWith(1))))); + VariantWith(0), + VariantWith(1), + VariantWith(1))))); // MUL last pos EXPECT_THAT(instructions.at(13), - AllOf(Field(&Instruction::op_code, OpCode::MUL), + AllOf(Field(&Instruction::op_code, OpCode::MUL_8), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(AvmMemoryTag::U64), - VariantWith(0), - VariantWith(1), - VariantWith(1))))); + VariantWith(0), + VariantWith(1), + VariantWith(1))))); // RETURN EXPECT_THAT(instructions.at(14), @@ -260,28 +259,28 @@ TEST_F(AvmExecutionTests, powerWithMulOpcodes) // 0 1 2 3 4 5 TEST_F(AvmExecutionTests, simpleInternalCall) { - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET + std::string bytecode_hex = to_hex(OpCode::SET_32) + // opcode SET "00" // Indirect flag "03" // U32 "0D3D2518" // val 222111000 = 0xD3D2518 - "00000004" // dst_offset 4 + "0004" // dst_offset 4 + to_hex(OpCode::INTERNALCALL) + // opcode INTERNALCALL "00000004" // jmp_dest - + to_hex(OpCode::ADD) + // opcode ADD + + to_hex(OpCode::ADD_16) + // opcode ADD "00" // Indirect flag "03" // U32 - "00000004" // addr a 4 - "00000007" // addr b 7 - "00000009" // addr c9 + "0004" // addr a 4 + "0007" // addr b 7 + "0009" // addr c9 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "00000000" // ret offset 0 "00000000" // ret size 0 - + to_hex(OpCode::SET) + // opcode SET + + to_hex(OpCode::SET_32) + // opcode SET "00" // Indirect flag "03" // U32 "075BCD15" // val 123456789 = 0x75BCD15 - "00000007" // dst_offset 7 + "0007" // dst_offset 7 + to_hex(OpCode::INTERNALRETURN) // opcode INTERNALRETURN ; @@ -336,28 +335,28 @@ TEST_F(AvmExecutionTests, nestedInternalCalls) }; auto setInstructionHex = [](std::string const& val, std::string const& dst_offset) { - return to_hex(OpCode::SET) // opcode SET - + "00" // Indirect flag - + "01" // U8 - + val + "000000" + dst_offset; + // val and dst_offset is assumed to be 2 bytes + return to_hex(OpCode::SET_32) // opcode SET + + "00" // Indirect flag + + "01" // U8 + + "000000" + val + "00" + dst_offset; }; - const std::string tag_address_arguments = "00" // Indirect Flag - "01" // U8 - "00000002" // addr a 2 - "00000003" // addr b 3 - "00000002"; // addr c 2 + const std::string tag_address_arguments = "00" // Indirect Flag + "01" // U8 + "02" // addr a 2 + "03" // addr b 3 + "02"; // addr c 2 const std::string return_instruction_hex = to_hex(OpCode::RETURN) // opcode RETURN + "00" // Indirect flag "00000000" // ret offset 0 "00000000"; // ret size 0 - const std::string bytecode_f1 = to_hex(OpCode::ADD) + tag_address_arguments + to_hex(OpCode::INTERNALRETURN); - const std::string bytecode_f2 = to_hex(OpCode::MUL) + tag_address_arguments + to_hex(OpCode::INTERNALRETURN); + const std::string bytecode_f1 = to_hex(OpCode::ADD_8) + tag_address_arguments + to_hex(OpCode::INTERNALRETURN); + const std::string bytecode_f2 = to_hex(OpCode::MUL_8) + tag_address_arguments + to_hex(OpCode::INTERNALRETURN); const std::string bytecode_g = internalCallInstructionHex("06") + setInstructionHex("11", "03") + internalCallInstructionHex("04") + to_hex(OpCode::INTERNALRETURN); - std::string bytecode_hex = setInstructionHex("04", "02") + setInstructionHex("07", "03") + internalCallInstructionHex("08") + return_instruction_hex + bytecode_f2 + bytecode_f1 + bytecode_g; @@ -368,12 +367,10 @@ TEST_F(AvmExecutionTests, nestedInternalCalls) ASSERT_THAT(instructions, SizeIs(12)); // Expected sequence of opcodes - std::vector const opcode_sequence{ OpCode::SET, OpCode::SET, - OpCode::INTERNALCALL, OpCode::RETURN, - OpCode::MUL, OpCode::INTERNALRETURN, - OpCode::ADD, OpCode::INTERNALRETURN, - OpCode::INTERNALCALL, OpCode::SET, - OpCode::INTERNALCALL, OpCode::INTERNALRETURN }; + std::vector const opcode_sequence{ OpCode::SET_32, OpCode::SET_32, OpCode::INTERNALCALL, + OpCode::RETURN, OpCode::MUL_8, OpCode::INTERNALRETURN, + OpCode::ADD_8, OpCode::INTERNALRETURN, OpCode::INTERNALCALL, + OpCode::SET_32, OpCode::INTERNALCALL, OpCode::INTERNALRETURN }; for (size_t i = 0; i < 12; i++) { EXPECT_EQ(instructions.at(i).op_code, opcode_sequence.at(i)); @@ -404,56 +401,69 @@ TEST_F(AvmExecutionTests, nestedInternalCalls) // 0 1 2 3 4 TEST_F(AvmExecutionTests, jumpAndCalldatacopy) { - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY (no in tag) - "00" // Indirect flag - "00000000" // cd_offset - "00000002" // copy_size - "0000000A" // dst_offset // M[10] = 13, M[11] = 156 - + to_hex(OpCode::JUMP) + // opcode JUMP - "00000003" // jmp_dest (FDIV located at 3) - + to_hex(OpCode::SUB) + // opcode SUB - "00" // Indirect flag - "06" // FF - "0000000B" // addr 11 - "0000000A" // addr 10 - "00000001" // addr c 1 (If executed would be 156 - 13 = 143) - + to_hex(OpCode::FDIV) + // opcode FDIV - "00" // Indirect flag - "0000000B" // addr 11 - "0000000A" // addr 10 - "00000001" // addr c 1 (156 / 13 = 12) - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "00000000" // ret offset 0 - "00000000" // ret size 0 + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset 101 + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "02" // val + "01" // dst_offset 101 + + to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY (no in tag) + "00" // Indirect flag + "00000000" // cd_offset + "00000001" // copy_size + "0000000A" // dst_offset // M[10] = 13, M[11] = 156 + + to_hex(OpCode::JUMP_16) + // opcode JUMP + "0005" // jmp_dest (FDIV located at 3) + + to_hex(OpCode::SUB_8) + // opcode SUB + "00" // Indirect flag + "06" // FF + "0B" // addr 11 + "0A" // addr 10 + "01" // addr c 1 (If executed would be 156 - 13 = 143) + + to_hex(OpCode::FDIV_8) + // opcode FDIV + "00" // Indirect flag + "06" // tag + "0B" // addr 11 + "0A" // addr 10 + "01" // addr c 1 (156 / 13 = 12) + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000000" // ret offset 0 + "00000000" // ret size 0 ; auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - ASSERT_THAT(instructions, SizeIs(5)); + ASSERT_THAT(instructions, SizeIs(7)); // We test parsing steps for CALLDATACOPY and JUMP. // CALLDATACOPY - EXPECT_THAT(instructions.at(0), + EXPECT_THAT(instructions.at(2), AllOf(Field(&Instruction::op_code, OpCode::CALLDATACOPY), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(0), - VariantWith(2), + VariantWith(1), VariantWith(10))))); // JUMP - EXPECT_THAT(instructions.at(1), - AllOf(Field(&Instruction::op_code, OpCode::JUMP), - Field(&Instruction::operands, ElementsAre(VariantWith(3))))); + EXPECT_THAT(instructions.at(3), + AllOf(Field(&Instruction::op_code, OpCode::JUMP_16), + Field(&Instruction::operands, ElementsAre(VariantWith(5))))); - std::vector returndata{}; + std::vector returndata; auto trace = Execution::gen_trace(instructions, returndata, std::vector{ 13, 156 }, public_inputs_vec); // Expected sequence of PCs during execution - std::vector pc_sequence{ 0, 1, 3, 4 }; + std::vector pc_sequence{ + 0, 1, 2, 3, 4, 6, + }; for (size_t i = 0; i < 4; i++) { EXPECT_EQ(trace.at(i + 1).main_pc, pc_sequence.at(i)); @@ -482,60 +492,70 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) // We test this bytecode with two calldatacopy values: 9873123 and 0. TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) { - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY (no in tag) - "00" // Indirect flag - "00000000" // cd_offset - "00000001" // copy_size - "0000000A" // dst_offset 10 - + to_hex(OpCode::SET) + // opcode SET - "00" // Indirect flag - "02" // U16 - "0014" // val 20 - "00000065" // dst_offset 101 - + to_hex(OpCode::JUMPI) + // opcode JUMPI - "00" // Indirect flag - "00000004" // jmp_dest (MUL located at 4) - "0000000A" // cond_offset 10 - + to_hex(OpCode::ADD) + // opcode ADD - "00" // Indirect flag - "02" // U16 - "00000065" // addr 101 - "00000065" // addr 101 - "00000065" // output addr 101 - + to_hex(OpCode::MUL) + // opcode MUL - "00" // Indirect flag - "02" // U16 - "00000065" // addr 101 - "00000065" // addr 101 - "00000066" // output of MUL addr 102 - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "00000000" // ret offset 0 - "00000000" // ret size 0 + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "01" // val + "01" // dst_offset + + to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY (no in tag) + "00" // Indirect flag + "00000000" // cd_offset + "00000001" // copy_size + "0000000A" // dst_offset 10 + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "02" // U16 + "14" // val 20 + "65" // dst_offset 101 + + to_hex(OpCode::JUMPI_16) + // opcode JUMPI + "00" // Indirect flag + "0006" // jmp_dest (MUL located at 6) + "000A" // cond_offset 10 + + to_hex(OpCode::ADD_16) + // opcode ADD + "00" // Indirect flag + "02" // U16 + "0065" // addr 101 + "0065" // addr 101 + "0065" // output addr 101 + + to_hex(OpCode::MUL_8) + // opcode MUL + "00" // Indirect flag + "02" // U16 + "65" // addr 101 + "65" // addr 101 + "66" // output of MUL addr 102 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000000" // ret offset 0 + "00000000" // ret size 0 ; auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - ASSERT_THAT(instructions, SizeIs(6)); + ASSERT_THAT(instructions, SizeIs(8)); // We test parsing of JUMPI. // JUMPI EXPECT_THAT( - instructions.at(2), - AllOf(Field(&Instruction::op_code, OpCode::JUMPI), + instructions.at(4), + AllOf(Field(&Instruction::op_code, OpCode::JUMPI_16), Field(&Instruction::operands, - ElementsAre(VariantWith(0), VariantWith(4), VariantWith(10))))); + ElementsAre(VariantWith(0), VariantWith(6), VariantWith(10))))); - std::vector returndata{}; + std::vector returndata; auto trace_jump = Execution::gen_trace(instructions, returndata, std::vector{ 9873123 }, public_inputs_vec); auto trace_no_jump = Execution::gen_trace(instructions, returndata, std::vector{ 0 }, public_inputs_vec); // Expected sequence of PCs during execution with jump - std::vector pc_sequence_jump{ 0, 1, 2, 4, 5 }; + std::vector pc_sequence_jump{ 0, 1, 2, 3, 4, 6, 7 }; // Expected sequence of PCs during execution without jump - std::vector pc_sequence_no_jump{ 0, 1, 2, 3, 4, 5 }; + std::vector pc_sequence_no_jump{ 0, 1, 2, 3, 4, 5, 6, 7 }; for (size_t i = 0; i < 5; i++) { EXPECT_EQ(trace_jump.at(i + 1).main_pc, pc_sequence_jump.at(i)); @@ -545,22 +565,6 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) EXPECT_EQ(trace_no_jump.at(i + 1).main_pc, pc_sequence_no_jump.at(i)); } - // JUMP CASE - // Find the first row enabling the MUL opcode - auto row = std::ranges::find_if(trace_jump.begin(), trace_jump.end(), [](Row r) { return r.main_sel_op_mul == 1; }); - EXPECT_EQ(row->main_ic, 400); // 400 = 20 * 20 - - // Find the first row enabling the addition selector. - row = std::ranges::find_if(trace_jump.begin(), trace_jump.end(), [](Row r) { return r.main_sel_op_add == 1; }); - // It must have failed as addition was "jumped over". - EXPECT_EQ(row, trace_jump.end()); - - // NO JUMP CASE - // Find the first row enabling the MUL opcode - row = - std::ranges::find_if(trace_no_jump.begin(), trace_no_jump.end(), [](Row r) { return r.main_sel_op_mul == 1; }); - EXPECT_EQ(row->main_ic, 1600); // 800 = (20 + 20) * (20 + 20) - // traces validation validate_trace(std::move(trace_jump), public_inputs, { 9873123 }); validate_trace(std::move(trace_no_jump), public_inputs, { 0 }); @@ -569,15 +573,15 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) // Positive test with MOV. TEST_F(AvmExecutionTests, movOpcode) { - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag "01" // U8 "13" // val 19 - "000000AB" // dst_offset 171 - + to_hex(OpCode::MOV) + // opcode MOV + "AB" // dst_offset 171 + + to_hex(OpCode::MOV_8) + // opcode MOV "00" // Indirect flag - "000000AB" // src_offset 171 - "00000021" // dst_offset 33 + "AB" // src_offset 171 + "21" // dst_offset 33 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "00000000" // ret offset 0 @@ -590,19 +594,19 @@ TEST_F(AvmExecutionTests, movOpcode) // SET EXPECT_THAT(instructions.at(0), - AllOf(Field(&Instruction::op_code, OpCode::SET), + AllOf(Field(&Instruction::op_code, OpCode::SET_8), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(AvmMemoryTag::U8), VariantWith(19), - VariantWith(171))))); + VariantWith(171))))); // MOV EXPECT_THAT( instructions.at(1), - AllOf(Field(&Instruction::op_code, OpCode::MOV), + AllOf(Field(&Instruction::op_code, OpCode::MOV_8), Field(&Instruction::operands, - ElementsAre(VariantWith(0), VariantWith(171), VariantWith(33))))); + ElementsAre(VariantWith(0), VariantWith(171), VariantWith(33))))); auto trace = gen_trace_from_instr(instructions); @@ -617,21 +621,21 @@ TEST_F(AvmExecutionTests, movOpcode) // Positive test with CMOV. TEST_F(AvmExecutionTests, cmovOpcode) { - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag "01" // U8 "03" // val 3 - "00000010" // a_offset 16 - + to_hex(OpCode::SET) + // opcode SET + "10" // a_offset 16 + + to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag "02" // U16 - "0004" // val 4 - "00000011" // b_offset 17 - + to_hex(OpCode::SET) + // opcode SET + "04" // val 4 + "11" // b_offset 17 + + to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag "03" // U32 - "00000005" // val 5 - "00000020" // cond_offset 32 + "05" // val 5 + "20" // cond_offset 32 + to_hex(OpCode::CMOV) + // opcode CMOV "00" // Indirect flag "00000010" // a_offset 16 @@ -673,25 +677,25 @@ TEST_F(AvmExecutionTests, cmovOpcode) // Positive test with indirect MOV. TEST_F(AvmExecutionTests, indMovOpcode) { - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag "03" // U32 - "0000000A" // val 10 - "00000001" // dst_offset 1 - + to_hex(OpCode::SET) + // opcode SET + "0A" // val 10 + "01" // dst_offset 1 + + to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag "03" // U32 - "0000000B" // val 11 - "00000002" // dst_offset 2 - + to_hex(OpCode::SET) + // opcode SET + "0B" // val 11 + "02" // dst_offset 2 + + to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag "01" // U8 "FF" // val 255 - "0000000A" // dst_offset 10 - + to_hex(OpCode::MOV) + // opcode MOV + "0A" // dst_offset 10 + + to_hex(OpCode::MOV_8) + // opcode MOV "01" // Indirect flag - "00000001" // src_offset 1 --> direct offset 10 - "00000002" // dst_offset 2 --> direct offset 11 + "01" // src_offset 1 --> direct offset 10 + "02" // dst_offset 2 --> direct offset 11 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "00000000" // ret offset 0 @@ -704,9 +708,9 @@ TEST_F(AvmExecutionTests, indMovOpcode) // MOV EXPECT_THAT(instructions.at(3), - AllOf(Field(&Instruction::op_code, OpCode::MOV), + AllOf(Field(&Instruction::op_code, OpCode::MOV_8), Field(&Instruction::operands, - ElementsAre(VariantWith(1), VariantWith(1), VariantWith(2))))); + ElementsAre(VariantWith(1), VariantWith(1), VariantWith(2))))); auto trace = gen_trace_from_instr(instructions); @@ -721,11 +725,11 @@ TEST_F(AvmExecutionTests, indMovOpcode) // Positive test for SET and CAST opcodes TEST_F(AvmExecutionTests, setAndCastOpcodes) { - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET + std::string bytecode_hex = to_hex(OpCode::SET_16) + // opcode SET "00" // Indirect flag "02" // U16 "B813" // val 47123 - "00000011" // dst_offset 17 + "0011" // dst_offset 17 + to_hex(OpCode::CAST) + // opcode CAST "00" // Indirect flag "01" // U8 @@ -762,37 +766,47 @@ TEST_F(AvmExecutionTests, setAndCastOpcodes) // Positive test with TO_RADIX_LE. TEST_F(AvmExecutionTests, toRadixLeOpcode) { - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY - "00" // Indirect flag - "00000000" // cd_offset - "00000001" // copy_size - "00000001" // dst_offset - + to_hex(OpCode::SET) + // opcode SET for indirect src - "00" // Indirect flag - "03" // U32 - "00000001" // value 1 (i.e. where the src from calldata is copied) - "00000011" // dst_offset 17 - + to_hex(OpCode::SET) + // opcode SET for indirect dst - "00" // Indirect flag - "03" // U32 - "00000005" // value 5 (i.e. where the dst will be written to) - "00000015" // dst_offset 21 - + to_hex(OpCode::TORADIXLE) + // opcode TO_RADIX_LE - "03" // Indirect flag - "00000011" // src_offset 17 (indirect) - "00000015" // dst_offset 21 (indirect) - "00000002" // radix: 2 (i.e. perform bitwise decomposition) - "00000100" // limbs: 256 - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "00000005" // ret offset 0 - "00000100"; // ret size 0 + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "01" // val + "01" // dst_offset + + to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY + "00" // Indirect flag + "00000000" // cd_offset + "00000001" // copy_size + "00000001" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET for indirect src + "00" // Indirect flag + "03" // U32 + "01" // value 1 (i.e. where the src from calldata is copied) + "11" // dst_offset 17 + + to_hex(OpCode::SET_8) + // opcode SET for indirect dst + "00" // Indirect flag + "03" // U32 + "05" // value 5 (i.e. where the dst will be written to) + "15" // dst_offset 21 + + to_hex(OpCode::TORADIXLE) + // opcode TO_RADIX_LE + "03" // Indirect flag + "00000011" // src_offset 17 (indirect) + "00000015" // dst_offset 21 (indirect) + "00000002" // radix: 2 (i.e. perform bitwise decomposition) + "00000100" // limbs: 256 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000005" // ret offset 0 + "00000100"; // ret size 0 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); // Assign a vector that we will mutate internally in gen_trace to store the return values; - std::vector returndata = std::vector(); + std::vector returndata; auto trace = Execution::gen_trace(instructions, returndata, std::vector{ FF::modulus - FF(1) }, public_inputs_vec); @@ -816,39 +830,39 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) // Set operations for sha256 state // Test vectors taken from noir black_box_solver // State = Uint32Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]), - for (uint32_t i = 1; i <= 8; i++) { - bytecode_preamble += to_hex(OpCode::SET) + // opcode SET - "00" // Indirect flag - "03" + // U32 - to_hex(i) + // val i - to_hex(i); // val i + for (uint8_t i = 1; i <= 8; i++) { + bytecode_preamble += to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" + // U32 + to_hex(i) + // val i + to_hex(i); // val i } // Set operations for sha256 input // Test vectors taken from noir black_box_solver // Input = Uint32Array.from([1, 2, 3, 4, 5, 6, 7, 8]), - for (uint32_t i = 1; i <= 16; i++) { - bytecode_preamble += to_hex(OpCode::SET) + // opcode SET - "00" // Indirect flag - "03" + // U32 - to_hex(i) + // val i - to_hex(i + 8); // val i + for (uint8_t i = 1; i <= 16; i++) { + bytecode_preamble += to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" + // U32 + to_hex(i) + // val i + to_hex(i + 8); // val i } - std::string bytecode_hex = bytecode_preamble // Initial SET operations to store state and input - + to_hex(OpCode::SET) + // opcode SET for indirect dst (output) - "00" // Indirect flag - "03" // U32 - "00000100" // value 256 (i.e. where the dst will be written to) - "00000024" // dst_offset 36 - + to_hex(OpCode::SET) + // opcode SET for indirect state - "00" // Indirect flag - "03" // U32 - "00000001" // value 1 (i.e. where the state will be read from) - "00000022" // dst_offset 34 - + to_hex(OpCode::SET) + // opcode SET for indirect input - "00" // Indirect flag - "03" // U32 - "00000009" // value 9 (i.e. where the input will be read from) - "00000023" // dst_offset 35 + std::string bytecode_hex = bytecode_preamble // Initial SET operations to store state and input + + to_hex(OpCode::SET_16) + // opcode SET for indirect dst (output) + "00" // Indirect flag + "03" // U32 + "0100" // value 256 (i.e. where the dst will be written to) + "0024" // dst_offset 36 + + to_hex(OpCode::SET_8) + // opcode SET for indirect state + "00" // Indirect flag + "03" // U32 + "01" // value 1 (i.e. where the state will be read from) + "22" // dst_offset 34 + + to_hex(OpCode::SET_8) + // opcode SET for indirect input + "00" // Indirect flag + "03" // U32 + "09" // value 9 (i.e. where the input will be read from) + "23" // dst_offset 35 + to_hex(OpCode::SHA256COMPRESSION) + // opcode SHA256COMPRESSION "07" // Indirect flag (first 3 operands indirect) "00000024" // output offset (indirect 36) @@ -892,36 +906,36 @@ TEST_F(AvmExecutionTests, sha256Opcode) FF(0xde), FF(0x5d), FF(0xae), FF(0x22), FF(0x23), FF(0xb0), FF(0x03), FF(0x61), FF(0xa3), FF(0x96), FF(0x17), FF(0x7a), FF(0x9c), FF(0xb4), FF(0x10), FF(0xff), FF(0x61), FF(0xf2), FF(0x00), FF(0x15), FF(0xad), }; - std::string bytecode_hex = to_hex(OpCode::SET) + // Initial SET operations to store state and input + std::string bytecode_hex = to_hex(OpCode::SET_8) + // Initial SET operations to store state and input "00" // Indirect Flag "01" // U8 "61" // val 97 - "00000001" // dst_offset 1 - + to_hex(OpCode::SET) + // opcode SET for indirect src (input) + "01" // dst_offset 1 + + to_hex(OpCode::SET_8) + // opcode SET for indirect src (input) "00" // Indirect flag "01" // U8 "62" // value 98 (i.e. where the src will be read from)A - "00000002" // input_offset 2 - + to_hex(OpCode::SET) + // opcode SET for indirect src (input) + "02" // input_offset 2 + + to_hex(OpCode::SET_8) + // opcode SET for indirect src (input) "00" // Indirect flag "01" // U32 "63" // value 99 (i.e. where the src will be read from) - "00000003" // input_offset 36 - + to_hex(OpCode::SET) + // opcode SET for indirect src (input) + "03" // input_offset 36 + + to_hex(OpCode::SET_8) + // opcode SET for indirect src (input) "00" // Indirect flag "03" // U32 - "00000001" // value 1 (i.e. where the src will be read from) - "00000024" // input_offset 36 - + to_hex(OpCode::SET) + // + "01" // value 1 (i.e. where the src will be read from) + "24" // input_offset 36 + + to_hex(OpCode::SET_8) + // "00" // Indirect flag "03" // U8 - "00000003" // value 3 (i.e. where the length parameter is stored) - "00000025" // input_offset 37 - + to_hex(OpCode::SET) + // opcode SET for indirect dst (output) + "03" // value 3 (i.e. where the length parameter is stored) + "25" // input_offset 37 + + to_hex(OpCode::SET_16) + // opcode SET for indirect dst (output) "00" // Indirect flag "03" // U32 - "00000100" // value 256 (i.e. where the ouput will be written to) - "00000023" // dst_offset 35 + "0100" // value 256 (i.e. where the ouput will be written to) + "0023" // dst_offset 35 + to_hex(OpCode::SHA256) + // opcode SHA256 "03" // Indirect flag (first 2 operands indirect) "00000023" // output offset (indirect 35) @@ -954,34 +968,39 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) FF(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")), FF(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")) }; - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // opcode CALL DATA COPY - "00" // Indirect Flag - "00000000" // cd_offset - "00000002" // copy_size - "00000001" // dst_offset 1 - + to_hex(OpCode::CALLDATACOPY) + - "00" - "00000002" - "00000002" - "00000003" + - to_hex(OpCode::SET) + // opcode SET for indirect src (input) - "00" // Indirect flag - "03" // U32 - "00000001" // value 1 (i.e. where the src will be read from) - "00000024" // dst_offset 36 - + to_hex(OpCode::SET) + // opcode SET for indirect dst (output) - "00" // Indirect flag - "03" // U32 - "00000009" // value 9 (i.e. where the ouput will be written to) - "00000023" // dst_offset 35 - + to_hex(OpCode::POSEIDON2) + // opcode POSEIDON2 - "03" // Indirect flag (first 2 operands indirect) - "00000024" // input offset (indirect 36) - "00000023" // output offset (indirect 35) - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "00000009" // ret offset 256 - "00000004"; // ret size 8 + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "04" // val + "01" // dst_offset + + to_hex(OpCode::CALLDATACOPY) + // opcode CALL DATA COPY + "00" // Indirect Flag + "00000000" // cd_offset + "00000001" // copy_size + "00000001" // dst_offset 1 + + to_hex(OpCode::SET_8) + // opcode SET for indirect src (input) + "00" // Indirect flag + "03" // U32 + "01" // value 1 (i.e. where the src will be read from) + "24" // dst_offset 36 + + to_hex(OpCode::SET_8) + // opcode SET for indirect dst (output) + "00" // Indirect flag + "03" // U32 + "09" // value 9 (i.e. where the ouput will be written to) + "23" // dst_offset 35 + + to_hex(OpCode::POSEIDON2) + // opcode POSEIDON2 + "03" // Indirect flag (first 2 operands indirect) + "00000024" // input offset (indirect 36) + "00000023" // output offset (indirect 35) + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000009" // ret offset 256 + "00000004"; // ret size 8 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); @@ -1027,31 +1046,31 @@ TEST_F(AvmExecutionTests, keccakf1600OpCode) std::string bytecode_preamble; // Set operations for keccak state - for (uint32_t i = 0; i < 25; i++) { - bytecode_preamble += to_hex(OpCode::SET) + // opcode SET + for (uint8_t i = 0; i < 25; i++) { + bytecode_preamble += to_hex(OpCode::SET_64) + // opcode SET "00" // Indirect flag "04" + // U64 to_hex(state[i]) + // val i - to_hex(i + 1); // dst offset + to_hex(i + 1); // dst offset } // We use calldatacopy twice because we need to set up 4 inputs std::string bytecode_hex = bytecode_preamble + // Initial SET operations to store state and input - to_hex(OpCode::SET) + // opcode SET for indirect src (input) + to_hex(OpCode::SET_8) + // opcode SET for indirect src (input) "00" // Indirect flag "03" // U32 - "00000001" // value 1 (i.e. where the src will be read from) - "00000024" // input_offset 36 - + to_hex(OpCode::SET) + // + "01" // value 1 (i.e. where the src will be read from) + "24" // input_offset 36 + + to_hex(OpCode::SET_8) + // "00" // Indirect flag "03" // U32 - "00000019" // value 25 (i.e. where the length parameter is stored) - "00000025" // input_offset 37 - + to_hex(OpCode::SET) + // opcode SET for indirect dst (output) + "19" // value 25 (i.e. where the length parameter is stored) + "25" // input_offset 37 + + to_hex(OpCode::SET_16) + // opcode SET for indirect dst (output) "00" // Indirect flag "03" // U32 - "00000100" // value 256 (i.e. where the ouput will be written to) - "00000023" // dst_offset 35 + "0100" // value 256 (i.e. where the ouput will be written to) + "0023" // dst_offset 35 + to_hex(OpCode::KECCAKF1600) + // opcode KECCAKF1600 "03" // Indirect flag (first 2 operands indirect) "00000023" // output offset (indirect 35) @@ -1078,7 +1097,6 @@ TEST_F(AvmExecutionTests, keccakf1600OpCode) // Positive test with Keccak. TEST_F(AvmExecutionTests, keccakOpCode) { - // Test vectors from keccak256_test_cases in noir/noir-repo/acvm-repo/blackbox_solver/ // Input: Uint8Array.from([0xbd]), // Output: Uint8Array.from([ @@ -1090,26 +1108,26 @@ TEST_F(AvmExecutionTests, keccakOpCode) FF(0x33), FF(0x65), FF(0x19), FF(0x37), FF(0xe8), FF(0x05), FF(0x27), FF(0x0c), FF(0xa3), FF(0xf3), FF(0xaf), FF(0x1c), FF(0x0d), FF(0xd2), FF(0x46), FF(0x2d), FF(0xca), FF(0x4b), FF(0x3b), FF(0x1a), FF(0xbf) }; - std::string bytecode_hex = to_hex(OpCode::SET) + // Initial SET operations to store state and input + std::string bytecode_hex = to_hex(OpCode::SET_8) + // Initial SET operations to store state and input "00" // Indirect Flag "01" // U8 "BD" // val 189 - "00000001" // dst_offset 1 - + to_hex(OpCode::SET) + // opcode SET for indirect src (input) + "01" // dst_offset 1 + + to_hex(OpCode::SET_8) + // opcode SET for indirect src (input) "00" // Indirect flag "03" // U32 - "00000001" // value 1 (i.e. where the src will be read from) - "00000024" // input_offset 36 - + to_hex(OpCode::SET) + // + "01" // value 1 (i.e. where the src will be read from) + "24" // input_offset 36 + + to_hex(OpCode::SET_8) + // "00" // Indirect flag "03" // U8 - "00000001" // value 1 (i.e. where the length parameter is stored) - "00000025" // input_offset 37 - + to_hex(OpCode::SET) + // opcode SET for indirect dst (output) + "01" // value 1 (i.e. where the length parameter is stored) + "25" // input_offset 37 + + to_hex(OpCode::SET_16) + // opcode SET for indirect dst (output) "00" // Indirect flag "03" // U32 - "00000100" // value 256 (i.e. where the ouput will be written to) - "00000023" // dst_offset 35 + "0100" // value 256 (i.e. where the ouput will be written to) + "0023" // dst_offset 35 + to_hex(OpCode::KECCAK) + // opcode KECCAK "03" // Indirect flag (first 2 operands indirect) "00000023" // output offset (indirect 35) @@ -1136,42 +1154,51 @@ TEST_F(AvmExecutionTests, keccakOpCode) // Positive test with Pedersen. TEST_F(AvmExecutionTests, pedersenHashOpCode) { - // Test vectors from pedersen_hash in noir/noir-repo/acvm-repo/blackbox_solver/ // input = [1,1] // output = 0x1c446df60816b897cda124524e6b03f36df0cec333fad87617aab70d7861daa6 // hash_index = 5; FF expected_output = FF("0x1c446df60816b897cda124524e6b03f36df0cec333fad87617aab70d7861daa6"); - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // Calldatacopy - "00" // Indirect flag - "00000000" // cd_offset - "00000002" // copy_size - "00000000" // dst_offset - + to_hex(OpCode::SET) + // opcode SET for direct hash index offset - "00" // Indirect flag - "03" // U32 - "00000005" // value 5 - "00000002" // input_offset 2 - + to_hex(OpCode::SET) + // opcode SET for indirect src - "00" // Indirect flag - "03" // U32 - "00000000" // value 0 (i.e. where the src will be read from) - "00000004" // dst_offset 4 - + to_hex(OpCode::SET) + // opcode SET for direct src_length - "00" // Indirect flag - "03" // U32 - "00000002" // value 2 - "00000005" // dst_offset - + to_hex(OpCode::PEDERSEN) + // opcode PEDERSEN - "04" // Indirect flag (3rd operand indirect) - "00000002" // hash_index offset (direct) - "00000003" // dest offset (direct) - "00000004" // input offset (indirect) - "00000005" // length offset (direct) - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "00000003" // ret offset 3 - "00000001"; // ret size 1 + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "02" // val + "01" // dst_offset + + to_hex(OpCode::CALLDATACOPY) + // Calldatacopy + "00" // Indirect flag + "00000000" // cd_offset + "00000001" // copy_size + "00000000" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET for direct hash index offset + "00" // Indirect flag + "03" // U32 + "05" // value 5 + "02" // input_offset 2 + + to_hex(OpCode::SET_8) + // opcode SET for indirect src + "00" // Indirect flag + "03" // U32 + "00" // value 0 (i.e. where the src will be read from) + "04" // dst_offset 4 + + to_hex(OpCode::SET_8) + // opcode SET for direct src_length + "00" // Indirect flag + "03" // U32 + "02" // value 2 + "05" // dst_offset + + to_hex(OpCode::PEDERSEN) + // opcode PEDERSEN + "04" // Indirect flag (3rd operand indirect) + "00000002" // hash_index offset (direct) + "00000003" // dest offset (direct) + "00000004" // input offset (indirect) + "00000005" // length offset (direct) + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000003" // ret offset 3 + "00000001"; // ret size 1 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); @@ -1196,31 +1223,36 @@ TEST_F(AvmExecutionTests, embeddedCurveAddOpCode) auto b_is_inf = b.is_point_at_infinity(); grumpkin::g1::affine_element res = a + b; auto expected_output = std::vector{ res.x, res.y, res.is_point_at_infinity() }; - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // Calldatacopy + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "06" // val + "01" // dst_offset + + to_hex(OpCode::CALLDATACOPY) + // Calldatacopy "00" // Indirect flag "00000000" // cd_offset - "00000002" // copy_size + "00000001" // copy_size "00000000" // dst_offset - + to_hex(OpCode::SET) + // opcode SET for direct src_length - "00" // Indirect flag - "01" // U8 - + to_hex(a_is_inf) + // - "00000002" // dst_offset - + to_hex(OpCode::CALLDATACOPY) + // calldatacopy + + to_hex(OpCode::CAST) + // opcode CAST inf to U8 "00" // Indirect flag - "00000002" // cd_offset - "00000002" // copy_size - "00000003" // dst_offset - + to_hex(OpCode::SET) + // opcode SET for direct src_length + "01" // U8 tag field + "00000002" // a_is_inf + "00000002" // a_is_inf + + to_hex(OpCode::CAST) + // opcode CAST inf to U8 "00" // Indirect flag - "01" // U32 - + to_hex(b_is_inf) + // value 2 - "00000005" // dst_offset - + to_hex(OpCode::SET) + // opcode SET for direct src_length + "01" // U8 tag field + "00000005" // b_is_inf + "00000005" // b_is_inf + + to_hex(OpCode::SET_8) + // opcode SET for direct src_length "00" // Indirect flag "03" // U32 - "00000007" // value - "00000006" // dst_offset + "07" // value + "06" // dst_offset + to_hex(OpCode::ECADD) + // opcode ECADD "40" // Indirect flag (sixth operand indirect) "00000000" // hash_index offset (direct) @@ -1240,7 +1272,7 @@ TEST_F(AvmExecutionTests, embeddedCurveAddOpCode) // Assign a vector that we will mutate internally in gen_trace to store the return values; std::vector returndata; - std::vector calldata = { a.x, a.y, b.x, b.y }; + std::vector calldata = { a.x, a.y, FF(a_is_inf ? 1 : 0), b.x, b.y, FF(b_is_inf ? 1 : 0) }; auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); EXPECT_EQ(returndata, expected_output); @@ -1267,10 +1299,20 @@ TEST_F(AvmExecutionTests, msmOpCode) // Send all the input as Fields and cast them to U8 later std::vector calldata = { FF(a.x), FF(a.y), a_is_inf, FF(b.x), FF(b.y), b_is_inf, scalar_a_lo, scalar_a_hi, scalar_b_lo, scalar_b_hi }; - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // Calldatacopy + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "0A" // val + "01" + + to_hex(OpCode::CALLDATACOPY) + // Calldatacopy "00" // Indirect flag "00000000" // cd_offset 0 - "0000000a" // copy_size (10 elements) + "00000001" // copy_size (10 elements) "00000000" // dst_offset 0 + to_hex(OpCode::CAST) + // opcode CAST inf to U8 "00" // Indirect flag @@ -1282,26 +1324,26 @@ TEST_F(AvmExecutionTests, msmOpCode) "01" // U8 tag field "00000005" // b_is_inf "00000005" // - + to_hex(OpCode::SET) + // opcode SET for length + + to_hex(OpCode::SET_8) + // opcode SET for length "00" // Indirect flag "03" // U32 - "00000006" // Length of point elements (6) - "0000000b" // dst offset (11) - + to_hex(OpCode::SET) + // SET Indirects + "06" // Length of point elements (6) + "0b" // dst offset (11) + + to_hex(OpCode::SET_8) + // SET Indirects "00" // Indirect flag "03" // U32 - "00000000" // points offset - "0000000d" // dst offset + - + to_hex(OpCode::SET) + // SET Indirects + "00" // points offset + "0d" // dst offset + + + to_hex(OpCode::SET_8) + // SET Indirects "00" // Indirect flag "03" // U32 - "00000006" // scalars offset - "0000000e" + // dst offset - to_hex(OpCode::SET) + // SET Indirects + "06" // scalars offset + "0e" + // dst offset + to_hex(OpCode::SET_8) + // SET Indirects "00" // Indirect flag "03" // U32 - "0000000c" // output offset - "0000000f" + // dst offset + "0c" // output offset + "0f" + // dst offset to_hex(OpCode::MSM) + // opcode MSM "07" // Indirect flag (first 3 indirect) "0000000d" // points offset @@ -1340,31 +1382,41 @@ TEST_F(AvmExecutionTests, pedersenCommitmentOpcode) std::vector expected_output = { expected_result.x, expected_result.y, expected_result.is_point_at_infinity() }; // Send all the input as Fields and cast them to U8 later std::vector calldata = { scalar_a, scalar_b }; - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // Calldatacopy + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "02" // val + "01" + + to_hex(OpCode::CALLDATACOPY) + // Calldatacopy "00" // Indirect flag "00000000" // cd_offset 0 - "00000002" // copy_size (2 elements) + "00000001" // copy_size (2 elements) "00000000" // dst_offset 0 - + to_hex(OpCode::SET) + // opcode SET for indirect input + + to_hex(OpCode::SET_8) + // opcode SET for indirect input "00" // Indirect flag "03" // U32 - "00000000" // Input stored at memory 0 - "0000000b" // dst offset (11) - + to_hex(OpCode::SET) + // opcode SET for indirect output + "00" // Input stored at memory 0 + "0b" // dst offset (11) + + to_hex(OpCode::SET_8) + // opcode SET for indirect output "00" // Indirect flag "03" // U32 - "00000020" // output offset - "0000000d" // dst offset - + to_hex(OpCode::SET) + // opcode SET for input length + "20" // output offset + "0d" // dst offset + + to_hex(OpCode::SET_8) + // opcode SET for input length "00" // Indirect flag "03" // U32 - "00000002" // scalars length (2) - "00000002" + // dst offset (2) - to_hex(OpCode::SET) + // opcode SET for ctx index + "02" // scalars length (2) + "02" + // dst offset (2) + to_hex(OpCode::SET_8) + // opcode SET for ctx index "00" // Indirect flag "03" // U32 - "00000000" // ctx index (0) - "0000000f" + // dst offset + "00" // ctx index (0) + "0f" + // dst offset to_hex(OpCode::PEDERSENCOMMITMENT) + // opcode MSM "03" // Indirect flag (first 2 indirect) "0000000b" // inputs offset @@ -1418,20 +1470,16 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) + to_hex(OpCode::TIMESTAMP) + // opcode TIMESTAMP "00" // Indirect flag "00000009" // dst_offset - // Not in simulator - // + to_hex(OpCode::COINBASE) + // opcode COINBASE - // "00" // Indirect flag - // "00000009" // dst_offset - + to_hex(OpCode::FEEPERL2GAS) + // opcode FEEPERL2GAS - "00" // Indirect flag - "0000000a" // dst_offset - + to_hex(OpCode::FEEPERDAGAS) + // opcode FEEPERDAGAS - "00" // Indirect flag - "0000000b" // dst_offset - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "00000001" // ret offset 1 - "0000000b"; // ret size 11 + + to_hex(OpCode::FEEPERL2GAS) + // opcode FEEPERL2GAS + "00" // Indirect flag + "0000000a" // dst_offset + + to_hex(OpCode::FEEPERDAGAS) + // opcode FEEPERDAGAS + "00" // Indirect flag + "0000000b" // dst_offset + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000001" // ret offset 1 + "0000000b"; // ret size 11 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); @@ -1483,13 +1531,6 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) AllOf(Field(&Instruction::op_code, OpCode::TIMESTAMP), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(9))))); - // COINBASE - // Not in simulator - // EXPECT_THAT(instructions.at(8), - // AllOf(Field(&Instruction::op_code, OpCode::COINBASE), - // Field(&Instruction::operands, ElementsAre(VariantWith(0), - // VariantWith(10))))); - // FEEPERL2GAS EXPECT_THAT(instructions.at(9), AllOf(Field(&Instruction::op_code, OpCode::FEEPERL2GAS), @@ -1514,15 +1555,14 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) FF version = 7; FF blocknumber = 8; FF timestamp = 9; - // FF coinbase = 10; // Not in simulator FF feeperl2gas = 10; FF feeperdagas = 11; // The return data for this test should be a the opcodes in sequence, as the opcodes dst address lines up with // this array The returndata call above will then return this array std::vector const expected_returndata = { - address, storage_address, sender, function_selector, transaction_fee, chainid, version, - blocknumber, /*coinbase,*/ timestamp, feeperl2gas, feeperdagas, + address, storage_address, sender, function_selector, transaction_fee, chainid, + version, blocknumber, timestamp, feeperl2gas, feeperdagas, }; // Set up public inputs to contain the above values @@ -1540,8 +1580,6 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) public_inputs_vec[VERSION_OFFSET] = version; public_inputs_vec[BLOCK_NUMBER_OFFSET] = blocknumber; public_inputs_vec[TIMESTAMP_OFFSET] = timestamp; - // Not in the simulator yet - // public_inputs_vec[COINBASE_OFFSET] = coinbase; // Global variables - Gas public_inputs_vec[FEE_PER_DA_GAS_OFFSET] = feeperdagas; public_inputs_vec[FEE_PER_L2_GAS_OFFSET] = feeperl2gas; @@ -1597,12 +1635,6 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_timestamp == 1; }); EXPECT_EQ(timestamp_row->main_ia, timestamp); - // // Check coinbase - // Not in simulator - // auto coinbase_row = - // std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_coinbase == 1; }); - // EXPECT_EQ(coinbase_row->main_ia, coinbase); - // Check feeperdagas auto feeperdagas_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_fee_per_da_gas == 1; }); @@ -1619,11 +1651,11 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) // Positive test for L2GASLEFT opcode TEST_F(AvmExecutionTests, l2GasLeft) { - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET + std::string bytecode_hex = to_hex(OpCode::SET_16) + // opcode SET "00" // Indirect flag "03" // U32 - "00000101" // val 257 - "00000011" // dst_offset 17 + "0101" // val 257 + "0011" // dst_offset 17 + to_hex(OpCode::L2GASLEFT) + // opcode L2GASLEFT "01" // Indirect flag "00000011" // dst_offset (indirect addr: 17) @@ -1648,7 +1680,7 @@ TEST_F(AvmExecutionTests, l2GasLeft) auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_l2gasleft == 1; }); uint32_t expected_rem_gas = DEFAULT_INITIAL_L2_GAS - - static_cast(GAS_COST_TABLE.at(OpCode::SET).base_l2_gas_fixed_table) - + static_cast(GAS_COST_TABLE.at(OpCode::SET_8).base_l2_gas_fixed_table) - static_cast(GAS_COST_TABLE.at(OpCode::L2GASLEFT).base_l2_gas_fixed_table); EXPECT_EQ(row->main_ia, expected_rem_gas); @@ -1660,12 +1692,12 @@ TEST_F(AvmExecutionTests, l2GasLeft) // Positive test for DAGASLEFT opcode TEST_F(AvmExecutionTests, daGasLeft) { - std::string bytecode_hex = to_hex(OpCode::ADD) + // opcode ADD + std::string bytecode_hex = to_hex(OpCode::ADD_16) + // opcode ADD "00" // Indirect flag "03" // U32 - "00000007" // addr a 7 - "00000009" // addr b 9 - "00000001" // addr c 1 + "0007" // addr a 7 + "0009" // addr b 9 + "0001" // addr c 1 + to_hex(OpCode::DAGASLEFT) + // opcode DAGASLEFT "00" // Indirect flag "00000027" // dst_offset 39 @@ -1690,7 +1722,7 @@ TEST_F(AvmExecutionTests, daGasLeft) auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_dagasleft == 1; }); uint32_t expected_rem_gas = DEFAULT_INITIAL_DA_GAS - - static_cast(GAS_COST_TABLE.at(OpCode::ADD).base_da_gas_fixed_table) - + static_cast(GAS_COST_TABLE.at(OpCode::ADD_8).base_da_gas_fixed_table) - static_cast(GAS_COST_TABLE.at(OpCode::DAGASLEFT).base_da_gas_fixed_table); EXPECT_EQ(row->main_ia, expected_rem_gas); @@ -1720,11 +1752,11 @@ TEST_F(AvmExecutionTests, ExecutorThrowsWithIncorrectNumberOfPublicInputs) TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) { // Set values into the first register to emit - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode Set - "00" // Indirect flag - "03" // U32 - "00000001" // value 1 - "00000001" // dst_offset 1 + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode Set + "00" // Indirect flag + "03" // U32 + "01" // value 1 + "01" // dst_offset 1 // Cast set to field + to_hex(OpCode::CAST) + // opcode CAST "00" // Indirect flag @@ -1822,11 +1854,11 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) TEST_F(AvmExecutionTests, kernelOutputStorageLoadOpcodeSimple) { // Sload from a value that has not previously been written to will require a hint to process - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag "03" // U32 - "00000009" // value 9 - "00000001" // dst_offset 1 + "09" // value 9 + "01" // dst_offset 1 + to_hex(OpCode::CAST) + // opcode CAST (Cast set to field) "00" // Indirect flag "06" // tag field @@ -1878,10 +1910,20 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeSimple) { // SSTORE, write 2 elements of calldata to dstOffset 1 and 2. std::vector calldata = { 42, 123, 9, 10 }; - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "04" // val + "01" + + to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY "00" // Indirect flag "00000000" // cd_offset - "00000004" // copy_size + "00000001" // copy_size "00000001" // dst_offset, (i.e. where we store the addr) + to_hex(OpCode::SSTORE) + // opcode SSTORE "00" // Indirect flag @@ -1895,9 +1937,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeSimple) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - ASSERT_THAT(instructions, SizeIs(3)); - - std::vector returndata = {}; + std::vector returndata; auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); // CHECK SSTORE @@ -1926,11 +1966,11 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeSimple) TEST_F(AvmExecutionTests, kernelOutputStorageOpcodes) { // Sload from a value that has not previously been written to will require a hint to process - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET - "00" // Indirect flag - "03" // U32 - "00000009" // value 9 - "00000001" // dst_offset 1 + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "09" // value 9 + "01" // dst_offset 1 // Cast set to field + to_hex(OpCode::CAST) + // opcode CAST "00" // Indirect flag @@ -2001,11 +2041,11 @@ TEST_F(AvmExecutionTests, kernelOutputStorageOpcodes) TEST_F(AvmExecutionTests, kernelOutputHashExistsOpcodes) { // hash exists from a value that has not previously been written to will require a hint to process - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET - "00" // Indirect flag - "03" // U32 - "00000001" // value 1 - "00000001" // dst_offset 1 + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "01" // value 1 + "01" // dst_offset 1 // Cast set to field + to_hex(OpCode::CAST) + // opcode CAST "00" // Indirect flag @@ -2072,9 +2112,9 @@ TEST_F(AvmExecutionTests, kernelOutputHashExistsOpcodes) trace.begin(), trace.end(), [&](Row r) { return r.main_clk == START_NULLIFIER_EXISTS_OFFSET; }); EXPECT_EQ(nullifier_out_row->main_kernel_value_out, 1); // value // TODO(#8287) - // EXPECT_EQ(nullifier_out_row->main_kernel_side_effect_out, 1); + EXPECT_EQ(nullifier_out_row->main_kernel_side_effect_out, 0); EXPECT_EQ(nullifier_out_row->main_kernel_metadata_out, 1); // exists - feed_output(START_NULLIFIER_EXISTS_OFFSET, 1, 1, 1); + feed_output(START_NULLIFIER_EXISTS_OFFSET, 1, 0, 1); // CHECK L1TOL2MSGEXISTS auto l1_to_l2_row = @@ -2087,9 +2127,9 @@ TEST_F(AvmExecutionTests, kernelOutputHashExistsOpcodes) trace.begin(), trace.end(), [&](Row r) { return r.main_clk == START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET; }); EXPECT_EQ(msg_out_row->main_kernel_value_out, 1); // value // TODO(#8287) - // EXPECT_EQ(msg_out_row->main_kernel_side_effect_out, 2); + EXPECT_EQ(msg_out_row->main_kernel_side_effect_out, 0); EXPECT_EQ(msg_out_row->main_kernel_metadata_out, 1); // exists - feed_output(START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET, 1, 2, 1); + feed_output(START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET, 1, 0, 1); validate_trace(std::move(trace), public_inputs); } @@ -2100,46 +2140,56 @@ TEST_F(AvmExecutionTests, opCallOpcodes) std::vector calldata = { 17, 10, 34802342, 1, 2, 3, 4 }; std::string bytecode_preamble; // Set up Gas offsets - bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for gas offset indirect - "00" // Indirect flag - "03" // U32 - "00000000" // val 0 (address where gas tuple is located) - "00000011"; // dst_offset 17 + bytecode_preamble += to_hex(OpCode::SET_8) + // opcode SET for gas offset indirect + "00" // Indirect flag + "03" // U32 + "00" // val 0 (address where gas tuple is located) + "11"; // dst_offset 17 // Set up contract address offset - bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for args offset indirect - "00" // Indirect flag - "03" // U32 - "00000002" // val 2 (where contract address is located) - "00000012"; // dst_offset 18 + bytecode_preamble += to_hex(OpCode::SET_8) + // opcode SET for args offset indirect + "00" // Indirect flag + "03" // U32 + "02" // val 2 (where contract address is located) + "12"; // dst_offset 18 // Set up args offset - bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for ret offset indirect - "00" // Indirect flag - "03" // U32 - "00000003" // val 3 (the start of the args array) - "00000013"; // dst_offset 19 + bytecode_preamble += to_hex(OpCode::SET_8) + // opcode SET for ret offset indirect + "00" // Indirect flag + "03" // U32 + "03" // val 3 (the start of the args array) + "13"; // dst_offset 19 // Set up args size offset - bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for ret offset indirect - "00" // Indirect flag - "03" // U32 - "00000004" // val 4 (the length of the args array) - "00000014"; // dst_offset 20 + bytecode_preamble += to_hex(OpCode::SET_8) + // opcode SET for ret offset indirect + "00" // Indirect flag + "03" // U32 + "04" // val 4 (the length of the args array) + "14"; // dst_offset 20 // Set up the ret offset - bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for ret offset indirect - "00" // Indirect flag - "03" // U32 - "00000100" // val 256 (the start of where to write the return data) - "00000015"; // dst_offset 21 + bytecode_preamble += to_hex(OpCode::SET_16) + // opcode SET for ret offset indirect + "00" // Indirect flag + "03" // U32 + "0100" // val 256 (the start of where to write the return data) + "0015"; // dst_offset 21 // Set up the success offset - bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for ret offset indirect - "00" // Indirect flag - "03" // U32 - "00000102" // val 258 (write the success flag at ret_offset + ret_size) - "00000016"; // dst_offset 22 - - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY + bytecode_preamble += to_hex(OpCode::SET_16) + // opcode SET for ret offset indirect + "00" // Indirect flag + "03" // U32 + "0102" // val 258 (write the success flag at ret_offset + ret_size) + "0016"; // dst_offset 22 + + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "07" // val + "01" + + to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY "00" // Indirect flag "00000000" // cd_offset - "00000007" // copy_size + "00000001" // copy_size "00000000" // dst_offset + bytecode_preamble // Load up memory offsets + to_hex(OpCode::CALL) + // opcode CALL @@ -2179,16 +2229,26 @@ TEST_F(AvmExecutionTests, opCallOpcodes) TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) { - std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY for addr + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + "03" // U32 + "01" // val + "01" + + to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY for addr "00" // Indirect flag "00000000" // cd_offset "00000001" // copy_size "00000001" // dst_offset, (i.e. where we store the addr) - + to_hex(OpCode::SET) + // opcode SET for the indirect dst offset + + to_hex(OpCode::SET_8) + // opcode SET for the indirect dst offset "00" // Indirect flag "03" // U32 - "00000003" // val i - "00000002" + // dst_offset 2 + "03" // val i + "02" + // dst_offset 2 to_hex(OpCode::GETCONTRACTINSTANCE) + // opcode CALL "02" // Indirect flag "00000001" // address offset @@ -2218,15 +2278,15 @@ TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) // Negative test detecting an invalid opcode byte. TEST_F(AvmExecutionTests, invalidOpcode) { - std::string bytecode_hex = to_hex(OpCode::ADD) + // opcode ADD - "00" // Indirect flag - "02" // U16 - "00000007" // addr a 7 - "00000009" // addr b 9 - "00000001" // addr c 1 - "AB" // Invalid opcode byte - "00000000" // ret offset 0 - "00000000"; // ret size 0 + std::string bytecode_hex = to_hex(OpCode::ADD_16) + // opcode ADD + "00" // Indirect flag + "02" // U16 + "0007" // addr a 7 + "0009" // addr b 9 + "0001" // addr c 1 + "AB" // Invalid opcode byte + "00000000" // ret offset 0 + "00000000"; // ret size 0 auto bytecode = hex_to_bytes(bytecode_hex); EXPECT_THROW_WITH_MESSAGE(Deserialization::parse(bytecode), "Invalid opcode"); @@ -2235,12 +2295,12 @@ TEST_F(AvmExecutionTests, invalidOpcode) // Negative test detecting an invalid memmory instruction tag. TEST_F(AvmExecutionTests, invalidInstructionTag) { - std::string bytecode_hex = to_hex(OpCode::ADD) + // opcode ADD + std::string bytecode_hex = to_hex(OpCode::ADD_16) + // opcode ADD "00" // Indirect flag "00" // Wrong type - "00000007" // addr a 7 - "00000009" // addr b 9 - "00000001" // addr c 1 + "0007" // addr a 7 + "0009" // addr b 9 + "0001" // addr c 1 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "00000000" // ret offset 0 @@ -2250,50 +2310,16 @@ TEST_F(AvmExecutionTests, invalidInstructionTag) EXPECT_THROW_WITH_MESSAGE(Deserialization::parse(bytecode), "Instruction tag is invalid"); } -// Negative test detecting SET opcode with instruction memory tag set to FF. -TEST_F(AvmExecutionTests, ffInstructionTagSetOpcode) -{ - std::string bytecode_hex = "00" // ADD - "00" // Indirect flag - "05" // U128 - "00000007" // addr a 7 - "00000009" // addr b 9 - "00000001" // addr c 1 - + to_hex(OpCode::SET) + // opcode SET - "00" // Indirect flag - "06" // tag FF - "00002344"; // - - auto bytecode = hex_to_bytes(bytecode_hex); - EXPECT_THROW_WITH_MESSAGE(Deserialization::parse(bytecode), "Instruction tag for SET opcode is invalid"); -} - -// Negative test detecting SET opcode without any operand. -TEST_F(AvmExecutionTests, SetOpcodeNoOperand) -{ - std::string bytecode_hex = "00" // ADD - "00" // Indirect flag - "05" // U128 - "00000007" // addr a 7 - "00000009" // addr b 9 - "00000001" // addr c 1 - + to_hex(OpCode::SET) + // opcode SET - "00"; // Indirect flag - - auto bytecode = hex_to_bytes(bytecode_hex); - EXPECT_THROW_WITH_MESSAGE(Deserialization::parse(bytecode), "Operand for SET opcode is missing"); -} - // Negative test detecting an incomplete instruction: missing instruction tag TEST_F(AvmExecutionTests, truncatedInstructionNoTag) { - std::string bytecode_hex = to_hex(OpCode::ADD) + // opcode ADD - "00" // Indirect flag - "02" // U16 - "00000007" // addr a 7 - "00000009" // addr b 9 - "00000001" // addr c 1 - + to_hex(OpCode::SUB); // opcode SUB + std::string bytecode_hex = to_hex(OpCode::ADD_16) + // opcode ADD + "00" // Indirect flag + "02" // U16 + "0007" // addr a 7 + "0009" // addr b 9 + "0001" // addr c 1 + + to_hex(OpCode::SUB_8); // opcode SUB auto bytecode = hex_to_bytes(bytecode_hex); EXPECT_THROW_WITH_MESSAGE(Deserialization::parse(bytecode), "Operand is missing"); @@ -2302,17 +2328,17 @@ TEST_F(AvmExecutionTests, truncatedInstructionNoTag) // Negative test detecting an incomplete instruction: instruction tag present but an operand is missing TEST_F(AvmExecutionTests, truncatedInstructionNoOperand) { - std::string bytecode_hex = to_hex(OpCode::ADD) + // opcode ADD - "00" // Indirect flag - "02" // U16 - "00000007" // addr a 7 - "00000009" // addr b 9 - "00000001" // addr c 1 - + to_hex(OpCode::SUB) + // opcode SUB - "00" // Indirect flag - "04" // U64 - "AB2373E7" // addr a - "FFFFFFBB"; // addr b and missing address for c = a-b + std::string bytecode_hex = to_hex(OpCode::ADD_16) + // opcode ADD + "00" // Indirect flag + "02" // U16 + "0007" // addr a 7 + "0009" // addr b 9 + "0001" // addr c 1 + + to_hex(OpCode::SUB_8) + // opcode SUB + "00" // Indirect flag + "04" // U64 + "AB" // addr a + "FF"; // addr b and missing address for c = a-b auto bytecode = hex_to_bytes(bytecode_hex); EXPECT_THROW_WITH_MESSAGE(Deserialization::parse(bytecode), "Operand is missing"); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp index d20103006f2..98aa04b7e66 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp @@ -148,8 +148,7 @@ class AvmRangeCheckNegativeTests : public AvmInterTableTests { void SetUp() override { GTEST_SKIP(); } - void genTraceAdd( - uint128_t const& a, uint128_t const& b, uint128_t const& c, AvmMemoryTag tag, uint32_t min_trace_size = 0) + void genTraceAdd(FF const& a, FF const& b, FF const& c, AvmMemoryTag tag, uint32_t min_trace_size = 0) { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); @@ -161,9 +160,9 @@ class AvmRangeCheckNegativeTests : public AvmInterTableTests { auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_add == FF(1); }); ASSERT_TRUE(row != trace.end()); - ASSERT_EQ(row->main_ia, FF(uint256_t::from_uint128(a))); - ASSERT_EQ(row->main_ib, FF(uint256_t::from_uint128(b))); - ASSERT_EQ(row->main_ic, FF(uint256_t::from_uint128(c))); + ASSERT_EQ(row->main_ia, a); + ASSERT_EQ(row->main_ib, b); + ASSERT_EQ(row->main_ic, c); auto clk = row->main_clk; // Find the corresponding Alu trace row @@ -400,7 +399,7 @@ class AvmPermMainMemNegativeTests : public AvmInterTableTests { // Helper function to generate a trace with a subtraction // for c = a - b at arbitray chosen addresses 52 (a), 11 (b), 55 (c). - void executeSub(uint128_t const a, uint128_t const b) + void executeSub(FF const a, FF const b) { trace_builder.op_set(0, a, 52, AvmMemoryTag::U8); trace_builder.op_set(0, b, 11, AvmMemoryTag::U8); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp index cc80b967fcd..b18553f1f2c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp @@ -525,40 +525,6 @@ TEST_F(AvmKernelPositiveTests, kernelBlockNumber) test_kernel_lookup(true, indirect_apply_opcodes, checks); } -TEST_F(AvmKernelPositiveTests, kernelCoinbase) -{ - uint32_t dst_offset = 42; - uint32_t indirect_dst_offset = 69; - auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { - trace_builder.op_coinbase(/*indirect*/ false, dst_offset); - }; - auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { - trace_builder.op_set( - /*indirect*/ false, - /*value*/ dst_offset, - /*dst_offset*/ indirect_dst_offset, - AvmMemoryTag::U32); - trace_builder.op_coinbase(/*indirect*/ true, indirect_dst_offset); - }; - - auto checks = [=](bool indirect, const std::vector& trace) { - auto fee_row = - std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_coinbase == FF(1); }); - EXPECT_TRUE(fee_row != trace.end()); - - expect_row(fee_row, - /*kernel_in_offset=*/COINBASE_SELECTOR, - /*ia=*/COINBASE_SELECTOR + - 1, // Note the value generated above for public inputs is the same as the index read + 1 - /*ind_a*/ indirect ? indirect_dst_offset : 0, - /*mem_addr_a*/ dst_offset, - /*w_in_tag=*/AvmMemoryTag::FF); - }; - - test_kernel_lookup(false, direct_apply_opcodes, checks); - test_kernel_lookup(true, indirect_apply_opcodes, checks); -} - TEST_F(AvmKernelPositiveTests, kernelTimestamp) { uint32_t dst_offset = 42; @@ -913,32 +879,6 @@ TEST_F(AvmKernelNegativeTests, incorrectIaTimestamp) negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } -TEST_F(AvmKernelNegativeTests, incorrectIaCoinbase) -{ - uint32_t dst_offset = 42; - FF incorrect_ia = FF(69); - - // We test that the sender opcode is inlcuded at index x in the public inputs - auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { - trace_builder.op_coinbase(/*indirect*/ false, dst_offset); - }; - auto checks = [=](bool indirect, const std::vector& trace) { - auto row = - std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_coinbase == FF(1); }); - EXPECT_TRUE(row != trace.end()); - - expect_row( - row, - /*kernel_in_offset=*/COINBASE_SELECTOR, - /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 - /*ind_a*/ indirect, - /*mem_addr_a=*/dst_offset, - /*w_in_tag=*/AvmMemoryTag::FF); - }; - - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); -} - // KERNEL OUTPUTS class AvmKernelOutputPositiveTests : public AvmKernelTests { protected: @@ -1141,7 +1081,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSload) auto execution_hints = ExecutionHints().with_storage_value_hints({ { 0, value } }); auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { - trace_builder.op_set(0, static_cast(slot), slot_offset, AvmMemoryTag::FF); + trace_builder.op_set(0, slot, slot_offset, AvmMemoryTag::FF); trace_builder.op_sload(indirect, slot_offset, size, dest_offset); }; auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { @@ -1181,8 +1121,8 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSstore) uint32_t output_offset = START_SSTORE_WRITE_OFFSET; auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { - trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); - trace_builder.op_set(0, static_cast(slot), metadata_offset, AvmMemoryTag::FF); + trace_builder.op_set(0, value, value_offset, AvmMemoryTag::FF); + trace_builder.op_set(0, slot, metadata_offset, AvmMemoryTag::FF); trace_builder.op_sstore(indirect, value_offset, size, metadata_offset); }; auto checks = [=]([[maybe_unused]] bool indirect, const std::vector& trace) { @@ -1225,13 +1165,13 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNoteHashExists) auto execution_hints = ExecutionHints().with_note_hash_exists_hints({ { 0, exists } }); auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { - trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); + trace_builder.op_set(0, value, value_offset, AvmMemoryTag::FF); // TODO(#8287): Leaf index isnt constrained properly so we just set it to 0 trace_builder.op_note_hash_exists(/*indirect*/ false, value_offset, 0, metadata_offset); }; // TODO: fix auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { - trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); + trace_builder.op_set(0, value, value_offset, AvmMemoryTag::FF); trace_builder.op_set(0, value_offset, indirect_value_offset, AvmMemoryTag::U32); trace_builder.op_set(0, metadata_offset, indirect_metadata_offset, AvmMemoryTag::U32); // TODO(#8287): Leaf index isnt constrained properly so we just set it to 0 @@ -1274,7 +1214,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierExists) auto execution_hints = ExecutionHints().with_nullifier_exists_hints({ { 0, exists } }); auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { - trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); + trace_builder.op_set(0, value, value_offset, AvmMemoryTag::FF); trace_builder.op_nullifier_exists(/*indirect=*/0, value_offset, metadata_offset); }; auto checks = [=](bool indirect, const std::vector& trace) { @@ -1313,7 +1253,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierNonExists) auto execution_hints = ExecutionHints().with_nullifier_exists_hints({ { 0, exists } }); auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { - trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); + trace_builder.op_set(0, value, value_offset, AvmMemoryTag::FF); trace_builder.op_nullifier_exists(/*indirect=*/0, value_offset, metadata_offset); }; auto checks = [=](bool indirect, const std::vector& trace) { @@ -1353,7 +1293,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelL1ToL2MsgExists) auto execution_hints = ExecutionHints().with_l1_to_l2_message_exists_hints({ { 0, exists } }); auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { - trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); + trace_builder.op_set(0, value, value_offset, AvmMemoryTag::FF); // TODO(#8287): Leaf index isnt constrained properly so we just set it to 0 trace_builder.op_l1_to_l2_msg_exists(/*indirect*/ false, value_offset, 0, metadata_offset); }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp index cfd90a2db00..84eed13b773 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp @@ -48,9 +48,9 @@ class AvmMemOpcodeTests : public ::testing::Test { if (indirect) { trace_builder.op_set(0, dir_src_offset, src_offset, AvmMemoryTag::U32); trace_builder.op_set(0, dir_dst_offset, dst_offset, AvmMemoryTag::U32); - trace_builder.op_set(0, val, dir_src_offset, tag); + trace_builder.op_set(0, uint256_t::from_uint128(val), dir_src_offset, tag); } else { - trace_builder.op_set(0, val, src_offset, tag); + trace_builder.op_set(0, uint256_t::from_uint128(val), src_offset, tag); } trace_builder.op_mov(indirect ? 3 : 0, src_offset, dst_offset); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp index cff791ab7dd..4a48913c483 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp @@ -38,7 +38,8 @@ TEST_F(AvmMemoryTests, mismatchedTagAddOperation) { std::vector const calldata = { 98, 12 }; trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); - trace_builder.op_calldata_copy(0, 0, 2, 0); + trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_add(0, 0, 1, 4, AvmMemoryTag::U8); trace_builder.op_return(0, 0, 0); @@ -231,7 +232,8 @@ TEST_F(AvmMemoryTests, readUninitializedMemoryViolation) TEST_F(AvmMemoryTests, mismatchedTagErrorViolation) { trace_builder = AvmTraceBuilder(public_inputs, {}, 0, { 98, 12 }); - trace_builder.op_calldata_copy(0, 0, 2, 0); + trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_sub(0, 0, 1, 4, AvmMemoryTag::U8); trace_builder.op_return(0, 0, 0); @@ -266,8 +268,9 @@ TEST_F(AvmMemoryTests, mismatchedTagErrorViolation) TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) { trace_builder = AvmTraceBuilder(public_inputs, {}, 0, std::vector{ 84, 7 }); - trace_builder.op_calldata_copy(0, 0, 2, 0); - trace_builder.op_fdiv(0, 0, 1, 4); + trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 0); + trace_builder.op_fdiv(0, 0, 1, 4, AvmMemoryTag::FF); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); @@ -292,8 +295,9 @@ TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) TEST_F(AvmMemoryTests, noErrorTagWriteViolation) { trace_builder = AvmTraceBuilder(public_inputs, {}, 0, { 84, 7 }); - trace_builder.op_calldata_copy(0, 0, 2, 0); - trace_builder.op_fdiv(0, 0, 1, 4); + trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 0); + trace_builder.op_fdiv(0, 0, 1, 4, AvmMemoryTag::FF); trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp index c5fa9a831b0..85e85f80c31 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp @@ -1,6 +1,7 @@ #include "barretenberg/vm/avm/tests/helpers.test.hpp" #include "barretenberg/vm/avm/trace/common.hpp" #include "common.test.hpp" +#include "gtest/gtest.h" #include #include @@ -39,7 +40,9 @@ class AvmSliceTests : public ::testing::Test { } gen_trace_builder(calldata); - trace_builder.op_calldata_copy(static_cast(indirect), col_offset, copy_size, dst_offset); + trace_builder.op_set(0, col_offset, 10000, AvmMemoryTag::U32); + trace_builder.op_set(0, copy_size, 10001, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(static_cast(indirect), 10000, 10001, dst_offset); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); } @@ -166,8 +169,11 @@ TEST_F(AvmSliceTests, twoCallsNoOverlap) calldata = { 2, 3, 4, 5, 6 }; gen_trace_builder(calldata); - trace_builder.op_calldata_copy(0, 0, 2, 34); - trace_builder.op_calldata_copy(0, 3, 2, 2123); + trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 0, 1, 34); + trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); + trace_builder.op_set(0, 2, 2, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(0, 1, 2, 2123); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -179,18 +185,18 @@ TEST_F(AvmSliceTests, twoCallsNoOverlap) main_rows.push_back(row); } - EXPECT_EQ(main_rows.size(), 2); + ASSERT_EQ(main_rows.size(), 2); EXPECT_THAT(main_rows.at(0), AllOf(MAIN_ROW_FIELD_EQ(ia, 0), MAIN_ROW_FIELD_EQ(ib, 2), MAIN_ROW_FIELD_EQ(mem_addr_c, 34), - MAIN_ROW_FIELD_EQ(clk, 1))); + MAIN_ROW_FIELD_EQ(clk, 2))); EXPECT_THAT(main_rows.at(1), AllOf(MAIN_ROW_FIELD_EQ(ia, 3), MAIN_ROW_FIELD_EQ(ib, 2), MAIN_ROW_FIELD_EQ(mem_addr_c, 2123), - MAIN_ROW_FIELD_EQ(clk, 2))); + MAIN_ROW_FIELD_EQ(clk, 5))); validate_trace(std::move(trace), public_inputs, calldata); } @@ -202,8 +208,11 @@ TEST_F(AvmSliceTests, indirectTwoCallsOverlap) gen_trace_builder(calldata); trace_builder.op_set(0, 34, 100, AvmMemoryTag::U32); // indirect address 100 resolves to 34 trace_builder.op_set(0, 2123, 101, AvmMemoryTag::U32); // indirect address 101 resolves to 2123 - trace_builder.op_calldata_copy(1, 1, 3, 100); - trace_builder.op_calldata_copy(1, 2, 3, 101); + trace_builder.op_set(0, 1, 1, AvmMemoryTag::U32); + trace_builder.op_set(0, 2, 2, AvmMemoryTag::U32); + trace_builder.op_set(0, 3, 3, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(4, 1, 3, 100); + trace_builder.op_calldata_copy(4, 2, 3, 101); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -223,14 +232,14 @@ TEST_F(AvmSliceTests, indirectTwoCallsOverlap) MAIN_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 1), MAIN_ROW_FIELD_EQ(ind_addr_c, 100), MAIN_ROW_FIELD_EQ(mem_addr_c, 34), - MAIN_ROW_FIELD_EQ(clk, 3))); + MAIN_ROW_FIELD_EQ(clk, 6))); EXPECT_THAT(main_rows.at(1), AllOf(MAIN_ROW_FIELD_EQ(ia, 2), MAIN_ROW_FIELD_EQ(ib, 3), MAIN_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 1), MAIN_ROW_FIELD_EQ(ind_addr_c, 101), MAIN_ROW_FIELD_EQ(mem_addr_c, 2123), - MAIN_ROW_FIELD_EQ(clk, 4))); + MAIN_ROW_FIELD_EQ(clk, 7))); validate_trace(std::move(trace), public_inputs, calldata); } @@ -241,7 +250,9 @@ TEST_F(AvmSliceTests, indirectFailedResolution) gen_trace_builder(calldata); trace_builder.op_set(0, 34, 100, AvmMemoryTag::U16); // indirect address 100 resolves to 34 - trace_builder.op_calldata_copy(1, 1, 3, 100); + trace_builder.op_set(0, 1, 1, AvmMemoryTag::U32); + trace_builder.op_set(0, 3, 3, AvmMemoryTag::U32); + trace_builder.op_calldata_copy(4, 1, 3, 100); trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.cpp index c57d298b59c..b305c233b85 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.cpp @@ -1,5 +1,6 @@ #include "barretenberg/vm/avm/trace/alu_trace.hpp" #include "barretenberg/vm/avm/trace/gadgets/range_check.hpp" +#include "barretenberg/vm/avm/trace/opcode.hpp" namespace bb::avm_trace { @@ -117,7 +118,7 @@ FF AvmAluTraceBuilder::op_add(FF const& a, FF const& b, AvmMemoryTag in_tag, uin alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ .alu_clk = clk, - .opcode = OpCode::ADD, + .opcode = OpCode::ADD_8, // FIXME: take into account all opcodes. .tag = in_tag, .alu_ia = a, .alu_ib = b, @@ -161,7 +162,7 @@ FF AvmAluTraceBuilder::op_sub(FF const& a, FF const& b, AvmMemoryTag in_tag, uin alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ .alu_clk = clk, - .opcode = OpCode::SUB, + .opcode = OpCode::SUB_8, // FIXME: take into account all opcodes. .tag = in_tag, .alu_ia = a, .alu_ib = b, @@ -213,7 +214,7 @@ FF AvmAluTraceBuilder::op_mul(FF const& a, FF const& b, AvmMemoryTag in_tag, uin alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ .alu_clk = clk, - .opcode = OpCode::MUL, + .opcode = OpCode::MUL_8, // FIXME: take into account all opcodes. .tag = in_tag, .alu_ia = a, .alu_ib = b, @@ -266,7 +267,7 @@ FF AvmAluTraceBuilder::op_div(FF const& a, FF const& b, AvmMemoryTag in_tag, uin AvmAluTraceBuilder::AluTraceEntry row{ .alu_clk = clk, - .opcode = OpCode::DIV, + .opcode = OpCode::DIV_8, // FIXME: take into account all opcodes. .tag = in_tag, .alu_ia = a, .alu_ib = b, @@ -313,7 +314,7 @@ FF AvmAluTraceBuilder::op_eq(FF const& a, FF const& b, AvmMemoryTag in_tag, uint alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ .alu_clk = clk, - .opcode = OpCode::EQ, + .opcode = OpCode::EQ_8, // FIXME: take into account all opcodes. .tag = in_tag, .alu_ia = a, .alu_ib = b, @@ -349,7 +350,7 @@ FF AvmAluTraceBuilder::op_lt(FF const& a, FF const& b, AvmMemoryTag in_tag, uint // The subtlety is here that the circuit is designed as a GT(x,y) circuit, therefore we swap the inputs a & b AvmAluTraceBuilder::AluTraceEntry row{ .alu_clk = clk, - .opcode = OpCode::LT, + .opcode = OpCode::LT_8, // FIXME: take into account all opcodes. .tag = in_tag, .alu_ia = a, .alu_ib = b, @@ -384,7 +385,7 @@ FF AvmAluTraceBuilder::op_lte(FF const& a, FF const& b, AvmMemoryTag in_tag, uin // Construct the row that performs the lte check AvmAluTraceBuilder::AluTraceEntry row{ .alu_clk = clk, - .opcode = OpCode::LTE, + .opcode = OpCode::LTE_8, // FIXME: take into account all opcodes. .tag = in_tag, .alu_ia = a, .alu_ib = b, @@ -473,7 +474,7 @@ FF AvmAluTraceBuilder::op_shl(FF const& a, FF const& b, AvmMemoryTag in_tag, uin } alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ .alu_clk = clk, - .opcode = OpCode::SHL, + .opcode = OpCode::SHL_8, // FIXME: take into account all opcodes. .tag = in_tag, .alu_ia = a, .alu_ib = b, @@ -536,7 +537,7 @@ FF AvmAluTraceBuilder::op_shr(FF const& a, FF const& b, AvmMemoryTag in_tag, uin alu_trace.push_back(AvmAluTraceBuilder::AluTraceEntry{ .alu_clk = clk, - .opcode = OpCode::SHR, + .opcode = OpCode::SHR_8, // FIXME: take into account all opcodes. .tag = in_tag, .alu_ia = a, .alu_ib = b, @@ -616,9 +617,10 @@ bool AvmAluTraceBuilder::is_range_check_required() const */ bool AvmAluTraceBuilder::is_alu_row_enabled(const AvmAluTraceBuilder::AluTraceEntry& r) { - return (r.opcode == OpCode::ADD || r.opcode == OpCode::SUB || r.opcode == OpCode::MUL || r.opcode == OpCode::EQ || - r.opcode == OpCode::NOT || r.opcode == OpCode::LT || r.opcode == OpCode::LTE || r.opcode == OpCode::SHR || - r.opcode == OpCode::SHL || r.opcode == OpCode::CAST || r.opcode == OpCode::DIV); + return (r.opcode == OpCode::ADD_8 || r.opcode == OpCode::SUB_8 || r.opcode == OpCode::MUL_8 || + r.opcode == OpCode::EQ_8 || r.opcode == OpCode::NOT || r.opcode == OpCode::LT_8 || + r.opcode == OpCode::LTE_8 || r.opcode == OpCode::SHR_8 || r.opcode == OpCode::SHL_8 || + r.opcode == OpCode::CAST || r.opcode == OpCode::DIV_8); } /** @@ -635,17 +637,17 @@ void AvmAluTraceBuilder::finalize(std::vector>& main_trace) dest.alu_sel_alu = FF(1); if (src.opcode.has_value()) { - dest.alu_op_add = FF(src.opcode == OpCode::ADD ? 1 : 0); - dest.alu_op_sub = FF(src.opcode == OpCode::SUB ? 1 : 0); - dest.alu_op_mul = FF(src.opcode == OpCode::MUL ? 1 : 0); + dest.alu_op_add = FF(src.opcode == OpCode::ADD_8 || src.opcode == OpCode::ADD_16 ? 1 : 0); + dest.alu_op_sub = FF(src.opcode == OpCode::SUB_8 || src.opcode == OpCode::SUB_16 ? 1 : 0); + dest.alu_op_mul = FF(src.opcode == OpCode::MUL_8 || src.opcode == OpCode::MUL_16 ? 1 : 0); dest.alu_op_not = FF(src.opcode == OpCode::NOT ? 1 : 0); - dest.alu_op_eq = FF(src.opcode == OpCode::EQ ? 1 : 0); - dest.alu_op_lt = FF(src.opcode == OpCode::LT ? 1 : 0); - dest.alu_op_lte = FF(src.opcode == OpCode::LTE ? 1 : 0); + dest.alu_op_eq = FF(src.opcode == OpCode::EQ_8 || src.opcode == OpCode::EQ_16 ? 1 : 0); + dest.alu_op_lt = FF(src.opcode == OpCode::LT_8 || src.opcode == OpCode::LT_16 ? 1 : 0); + dest.alu_op_lte = FF(src.opcode == OpCode::LTE_8 || src.opcode == OpCode::LTE_16 ? 1 : 0); dest.alu_op_cast = FF(src.opcode == OpCode::CAST ? 1 : 0); - dest.alu_op_shr = FF(src.opcode == OpCode::SHR ? 1 : 0); - dest.alu_op_shl = FF(src.opcode == OpCode::SHL ? 1 : 0); - dest.alu_op_div = FF(src.opcode == OpCode::DIV ? 1 : 0); + dest.alu_op_shr = FF(src.opcode == OpCode::SHR_8 || src.opcode == OpCode::SHR_16 ? 1 : 0); + dest.alu_op_shl = FF(src.opcode == OpCode::SHL_8 || src.opcode == OpCode::SHL_16 ? 1 : 0); + dest.alu_op_div = FF(src.opcode == OpCode::DIV_8 || src.opcode == OpCode::DIV_16 ? 1 : 0); } if (src.tag.has_value()) { diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp index bade655927c..b7854957ac4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp @@ -14,8 +14,11 @@ namespace bb::avm_trace { namespace { -const std::vector three_operand_format = { - OperandType::INDIRECT, OperandType::TAG, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, +const std::vector three_operand_format8 = { + OperandType::INDIRECT, OperandType::TAG, OperandType::UINT8, OperandType::UINT8, OperandType::UINT8, +}; +const std::vector three_operand_format16 = { + OperandType::INDIRECT, OperandType::TAG, OperandType::UINT16, OperandType::UINT16, OperandType::UINT16, }; const std::vector kernel_input_operand_format = { OperandType::INDIRECT, OperandType::UINT32 }; @@ -39,22 +42,35 @@ const std::vector external_call_format = { OperandType::INDIRECT, const std::unordered_map> OPCODE_WIRE_FORMAT = { // Compute // Compute - Arithmetic - { OpCode::ADD, three_operand_format }, - { OpCode::SUB, three_operand_format }, - { OpCode::MUL, three_operand_format }, - { OpCode::DIV, three_operand_format }, - { OpCode::FDIV, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, - // Compute - Comparators - { OpCode::EQ, three_operand_format }, - { OpCode::LT, three_operand_format }, - { OpCode::LTE, three_operand_format }, + { OpCode::ADD_8, three_operand_format8 }, + { OpCode::ADD_16, three_operand_format16 }, + { OpCode::SUB_8, three_operand_format8 }, + { OpCode::SUB_16, three_operand_format16 }, + { OpCode::MUL_8, three_operand_format8 }, + { OpCode::MUL_16, three_operand_format16 }, + { OpCode::DIV_8, three_operand_format8 }, + { OpCode::DIV_16, three_operand_format16 }, + { OpCode::FDIV_8, three_operand_format8 }, + { OpCode::FDIV_16, three_operand_format16 }, + // Compute - Comparison + { OpCode::EQ_8, three_operand_format8 }, + { OpCode::EQ_16, three_operand_format16 }, + { OpCode::LT_8, three_operand_format8 }, + { OpCode::LT_16, three_operand_format16 }, + { OpCode::LTE_8, three_operand_format8 }, + { OpCode::LTE_16, three_operand_format16 }, // Compute - Bitwise - { OpCode::AND, three_operand_format }, - { OpCode::OR, three_operand_format }, - { OpCode::XOR, three_operand_format }, - { OpCode::NOT, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT32, OperandType::UINT32 } }, - { OpCode::SHL, three_operand_format }, - { OpCode::SHR, three_operand_format }, + { OpCode::AND_8, three_operand_format8 }, + { OpCode::AND_16, three_operand_format16 }, + { OpCode::OR_8, three_operand_format8 }, + { OpCode::OR_16, three_operand_format16 }, + { OpCode::XOR_8, three_operand_format8 }, + { OpCode::XOR_16, three_operand_format16 }, + { OpCode::NOT, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT8, OperandType::UINT8 } }, + { OpCode::SHL_8, three_operand_format8 }, + { OpCode::SHL_16, three_operand_format16 }, + { OpCode::SHR_8, three_operand_format8 }, + { OpCode::SHR_16, three_operand_format16 }, // Compute - Type Conversions { OpCode::CAST, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT32, OperandType::UINT32 } }, @@ -68,14 +84,11 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::CHAINID, getter_format }, { OpCode::VERSION, getter_format }, { OpCode::BLOCKNUMBER, getter_format }, - // COINBASE, -- not in simulator { OpCode::TIMESTAMP, getter_format }, // Execution Environment - Globals - Gas { OpCode::FEEPERL2GAS, getter_format }, { OpCode::FEEPERDAGAS, getter_format }, - // BLOCKL2GASLIMIT, -- not in simulator - // BLOCKDAGASLIMIT, -- not in simulator - // + // Execution Environment - Calldata { OpCode::CALLDATACOPY, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, @@ -84,14 +97,20 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::DAGASLEFT, getter_format }, // Machine State - Internal Control Flow - { OpCode::JUMP, { OperandType::UINT32 } }, - { OpCode::JUMPI, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, + { OpCode::JUMP_16, { OperandType::UINT16 } }, + { OpCode::JUMPI_16, { OperandType::INDIRECT, OperandType::UINT16, OperandType::UINT16 } }, { OpCode::INTERNALCALL, { OperandType::UINT32 } }, { OpCode::INTERNALRETURN, {} }, // Machine State - Memory - // OpCode::SET is handled differently - { OpCode::MOV, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, + { OpCode::SET_8, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT8, OperandType::UINT8 } }, + { OpCode::SET_16, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT16, OperandType::UINT16 } }, + { OpCode::SET_32, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT32, OperandType::UINT16 } }, + { OpCode::SET_64, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT64, OperandType::UINT16 } }, + { OpCode::SET_128, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT128, OperandType::UINT16 } }, + { OpCode::SET_FF, { OperandType::INDIRECT, OperandType::TAG, OperandType::FF, OperandType::UINT16 } }, + { OpCode::MOV_8, { OperandType::INDIRECT, OperandType::UINT8, OperandType::UINT8 } }, + { OpCode::MOV_16, { OperandType::INDIRECT, OperandType::UINT16, OperandType::UINT16 } }, { OpCode::CMOV, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, @@ -179,7 +198,7 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = const std::unordered_map OPERAND_TYPE_SIZE = { { OperandType::INDIRECT, 1 }, { OperandType::TAG, 1 }, { OperandType::UINT8, 1 }, { OperandType::UINT16, 2 }, - { OperandType::UINT32, 4 }, { OperandType::UINT64, 8 }, { OperandType::UINT128, 16 }, + { OperandType::UINT32, 4 }, { OperandType::UINT64, 8 }, { OperandType::UINT128, 16 }, { OperandType::FF, 32 } }; } // Anonymous namespace @@ -210,58 +229,11 @@ std::vector Deserialization::parse(std::vector const& byte pos++; auto const opcode = static_cast(opcode_byte); - std::vector inst_format; - - if (opcode == OpCode::SET) { - // Small hack here because of the structure of SET (where Indirect is the first flag). - // Right now pos is pointing to the indirect flag, but we want it to point to the memory tag. - // We cannot increment pos again because we need to read from pos later when parsing the SET opcode - // So we effectively peek at the next pos - if (pos + 1 == length) { - throw_or_abort("Operand for SET opcode is missing at position " + std::to_string(pos)); - } - - std::set const valid_tags = { static_cast(AvmMemoryTag::U8), - static_cast(AvmMemoryTag::U16), - static_cast(AvmMemoryTag::U32), - static_cast(AvmMemoryTag::U64), - static_cast(AvmMemoryTag::U128) }; - // Peek again here for the mem tag - uint8_t set_tag_u8 = bytecode.at(pos + 1); - - if (!valid_tags.contains(set_tag_u8)) { - throw_or_abort("Instruction tag for SET opcode is invalid at position " + std::to_string(pos + 1) + - " value: " + std::to_string(set_tag_u8)); - } - - auto in_tag = static_cast(set_tag_u8); - switch (in_tag) { - case AvmMemoryTag::U8: - inst_format = { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT8, OperandType::UINT32 }; - break; - case AvmMemoryTag::U16: - inst_format = { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT16, OperandType::UINT32 }; - break; - case AvmMemoryTag::U32: - inst_format = { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT32, OperandType::UINT32 }; - break; - case AvmMemoryTag::U64: - inst_format = { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT64, OperandType::UINT32 }; - break; - case AvmMemoryTag::U128: - inst_format = { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT128, OperandType::UINT32 }; - break; - default: // This branch is guarded above. - throw_or_abort("Error processing wire format of SET opcode."); - } - } else { - auto const iter = OPCODE_WIRE_FORMAT.find(opcode); - if (iter == OPCODE_WIRE_FORMAT.end()) { - throw_or_abort("Opcode not found in OPCODE_WIRE_FORMAT: " + to_hex(opcode) + " name " + - to_string(opcode)); - } - inst_format = iter->second; + auto const iter = OPCODE_WIRE_FORMAT.find(opcode); + if (iter == OPCODE_WIRE_FORMAT.end()) { + throw_or_abort("Opcode not found in OPCODE_WIRE_FORMAT: " + to_hex(opcode) + " name " + to_string(opcode)); } + std::vector inst_format = iter->second; std::vector operands; for (OperandType const& opType : inst_format) { @@ -317,6 +289,12 @@ std::vector Deserialization::parse(std::vector const& byte operands.emplace_back(operand_u128); break; } + case OperandType::FF: { + FF operand_ff; + uint8_t const* pos_ptr = &bytecode.at(pos); + read(pos_ptr, operand_ff); + operands.emplace_back(operand_ff); + } } pos += OPERAND_TYPE_SIZE.at(opType); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.hpp index 42238d7c7b1..2a38e836f03 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.hpp @@ -11,7 +11,7 @@ namespace bb::avm_trace { // See avm/serialization/instruction_serialization.ts). // Note that the TAG enum value is not supported in TS and is parsed as UINT8. // INDIRECT is parsed as UINT8 where the bits represent the operands that have indirect mem access. -enum class OperandType : uint8_t { INDIRECT, TAG, UINT8, UINT16, UINT32, UINT64, UINT128 }; +enum class OperandType : uint8_t { INDIRECT, TAG, UINT8, UINT16, UINT32, UINT64, UINT128, FF }; class Deserialization { public: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index 8ae88df7bc9..6c6904fcac9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -153,7 +153,6 @@ std::tuple Execution::prove(std::vector const& public_in kernel_inputs[VERSION_SELECTOR] = public_inputs_vec[VERSION_OFFSET]; // Version kernel_inputs[BLOCK_NUMBER_SELECTOR] = public_inputs_vec[BLOCK_NUMBER_OFFSET]; // Block Number kernel_inputs[TIMESTAMP_SELECTOR] = public_inputs_vec[TIMESTAMP_OFFSET]; // Timestamp - kernel_inputs[COINBASE_SELECTOR] = public_inputs_vec[COINBASE_OFFSET]; // Coinbase // PublicCircuitPublicInputs - GlobalVariables - GasFees kernel_inputs[FEE_PER_DA_GAS_SELECTOR] = public_inputs_vec[FEE_PER_DA_GAS_OFFSET]; kernel_inputs[FEE_PER_L2_GAS_SELECTOR] = public_inputs_vec[FEE_PER_L2_GAS_OFFSET]; @@ -404,84 +402,158 @@ std::vector Execution::gen_trace(std::vector const& instructio switch (inst.op_code) { // Compute // Compute - Arithmetic - case OpCode::ADD: + case OpCode::ADD_8: trace_builder.op_add(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::ADD_16: + trace_builder.op_add(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - case OpCode::SUB: + case OpCode::SUB_8: trace_builder.op_sub(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - case OpCode::MUL: + case OpCode::SUB_16: + trace_builder.op_sub(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::MUL_8: trace_builder.op_mul(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::MUL_16: + trace_builder.op_mul(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - case OpCode::DIV: + case OpCode::DIV_8: trace_builder.op_div(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - case OpCode::FDIV: + case OpCode::DIV_16: + trace_builder.op_div(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::FDIV_8: trace_builder.op_fdiv(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3))); + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); break; - - // Compute - Comparators - case OpCode::EQ: + case OpCode::FDIV_16: + trace_builder.op_fdiv(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::EQ_8: trace_builder.op_eq(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::EQ_16: + trace_builder.op_eq(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::LT_8: + trace_builder.op_lt(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - case OpCode::LT: + case OpCode::LT_16: trace_builder.op_lt(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - case OpCode::LTE: + case OpCode::LTE_8: trace_builder.op_lte(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - - // Compute - Bitwise - case OpCode::AND: + case OpCode::LTE_16: + trace_builder.op_lte(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::AND_8: trace_builder.op_and(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::AND_16: + trace_builder.op_and(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - case OpCode::OR: + case OpCode::OR_8: + trace_builder.op_or(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::OR_16: trace_builder.op_or(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - case OpCode::XOR: + case OpCode::XOR_8: trace_builder.op_xor(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::XOR_16: + trace_builder.op_xor(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; case OpCode::NOT: @@ -490,18 +562,32 @@ std::vector Execution::gen_trace(std::vector const& instructio std::get(inst.operands.at(3)), std::get(inst.operands.at(1))); break; - case OpCode::SHL: + case OpCode::SHL_8: trace_builder.op_shl(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; - case OpCode::SHR: + case OpCode::SHL_16: + trace_builder.op_shl(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::SHR_8: trace_builder.op_shr(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(1))); + break; + case OpCode::SHR_16: + trace_builder.op_shr(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), std::get(inst.operands.at(1))); break; @@ -548,9 +634,6 @@ std::vector Execution::gen_trace(std::vector const& instructio case OpCode::TIMESTAMP: trace_builder.op_timestamp(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; - case OpCode::COINBASE: - trace_builder.op_coinbase(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); - break; case OpCode::FEEPERL2GAS: trace_builder.op_fee_per_l2_gas(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); @@ -577,13 +660,13 @@ std::vector Execution::gen_trace(std::vector const& instructio break; // Machine State - Internal Control Flow - case OpCode::JUMP: - trace_builder.op_jump(std::get(inst.operands.at(0))); + case OpCode::JUMP_16: + trace_builder.op_jump(std::get(inst.operands.at(0))); break; - case OpCode::JUMPI: + case OpCode::JUMPI_16: trace_builder.op_jumpi(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); break; case OpCode::INTERNALCALL: trace_builder.op_internal_call(std::get(inst.operands.at(0))); @@ -593,38 +676,57 @@ std::vector Execution::gen_trace(std::vector const& instructio break; // Machine State - Memory - case OpCode::SET: { - uint128_t val = 0; - AvmMemoryTag in_tag = std::get(inst.operands.at(1)); - - switch (in_tag) { - case AvmMemoryTag::U8: - val = std::get(inst.operands.at(2)); - break; - case AvmMemoryTag::U16: - val = std::get(inst.operands.at(2)); - break; - case AvmMemoryTag::U32: - val = std::get(inst.operands.at(2)); - break; - case AvmMemoryTag::U64: - val = std::get(inst.operands.at(2)); - break; - case AvmMemoryTag::U128: - val = std::get(inst.operands.at(2)); - break; - default: - break; - } - - trace_builder.op_set( - std::get(inst.operands.at(0)), val, std::get(inst.operands.at(3)), in_tag); + case OpCode::SET_8: { + trace_builder.op_set(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1))); + break; + } + case OpCode::SET_16: { + trace_builder.op_set(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1))); break; } - case OpCode::MOV: + case OpCode::SET_32: { + trace_builder.op_set(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1))); + break; + } + case OpCode::SET_64: { + trace_builder.op_set(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1))); + break; + } + case OpCode::SET_128: { + trace_builder.op_set(std::get(inst.operands.at(0)), + uint256_t::from_uint128(std::get(inst.operands.at(2))), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1))); + break; + } + case OpCode::SET_FF: { + trace_builder.op_set(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1))); + break; + } + case OpCode::MOV_8: + trace_builder.op_mov(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); + break; + case OpCode::MOV_16: trace_builder.op_mov(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); break; case OpCode::CMOV: trace_builder.op_cmov(std::get(inst.operands.at(0)), diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp index 76004cfa3d4..43005b68564 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp @@ -18,20 +18,33 @@ constexpr auto make_cost(uint16_t l2_base, uint16_t da_base, uint16_t l2_dyn, ui } const std::unordered_map GAS_COST_TABLE = { - { OpCode::ADD, make_cost(AVM_ADD_BASE_L2_GAS, 0, AVM_ADD_DYN_L2_GAS, 0) }, - { OpCode::SUB, make_cost(AVM_SUB_BASE_L2_GAS, 0, AVM_SUB_DYN_L2_GAS, 0) }, - { OpCode::MUL, make_cost(AVM_MUL_BASE_L2_GAS, 0, AVM_MUL_DYN_L2_GAS, 0) }, - { OpCode::DIV, make_cost(AVM_DIV_BASE_L2_GAS, 0, AVM_DIV_DYN_L2_GAS, 0) }, - { OpCode::FDIV, make_cost(AVM_FDIV_BASE_L2_GAS, 0, AVM_FDIV_DYN_L2_GAS, 0) }, - { OpCode::EQ, make_cost(AVM_EQ_BASE_L2_GAS, 0, AVM_EQ_DYN_L2_GAS, 0) }, - { OpCode::LT, make_cost(AVM_LT_BASE_L2_GAS, 0, AVM_LT_DYN_L2_GAS, 0) }, - { OpCode::LTE, make_cost(AVM_LTE_BASE_L2_GAS, 0, AVM_LTE_DYN_L2_GAS, 0) }, - { OpCode::AND, make_cost(AVM_AND_BASE_L2_GAS, 0, AVM_AND_DYN_L2_GAS, 0) }, - { OpCode::OR, make_cost(AVM_OR_BASE_L2_GAS, 0, AVM_OR_DYN_L2_GAS, 0) }, - { OpCode::XOR, make_cost(AVM_XOR_BASE_L2_GAS, 0, AVM_XOR_DYN_L2_GAS, 0) }, + { OpCode::ADD_8, make_cost(AVM_ADD_BASE_L2_GAS, 0, AVM_ADD_DYN_L2_GAS, 0) }, + { OpCode::ADD_16, make_cost(AVM_ADD_BASE_L2_GAS, 0, AVM_ADD_DYN_L2_GAS, 0) }, + { OpCode::SUB_8, make_cost(AVM_SUB_BASE_L2_GAS, 0, AVM_SUB_DYN_L2_GAS, 0) }, + { OpCode::SUB_16, make_cost(AVM_SUB_BASE_L2_GAS, 0, AVM_SUB_DYN_L2_GAS, 0) }, + { OpCode::MUL_8, make_cost(AVM_MUL_BASE_L2_GAS, 0, AVM_MUL_DYN_L2_GAS, 0) }, + { OpCode::MUL_16, make_cost(AVM_MUL_BASE_L2_GAS, 0, AVM_MUL_DYN_L2_GAS, 0) }, + { OpCode::DIV_8, make_cost(AVM_DIV_BASE_L2_GAS, 0, AVM_DIV_DYN_L2_GAS, 0) }, + { OpCode::DIV_16, make_cost(AVM_DIV_BASE_L2_GAS, 0, AVM_DIV_DYN_L2_GAS, 0) }, + { OpCode::FDIV_8, make_cost(AVM_FDIV_BASE_L2_GAS, 0, AVM_FDIV_DYN_L2_GAS, 0) }, + { OpCode::FDIV_16, make_cost(AVM_FDIV_BASE_L2_GAS, 0, AVM_FDIV_DYN_L2_GAS, 0) }, + { OpCode::EQ_8, make_cost(AVM_EQ_BASE_L2_GAS, 0, AVM_EQ_DYN_L2_GAS, 0) }, + { OpCode::EQ_16, make_cost(AVM_EQ_BASE_L2_GAS, 0, AVM_EQ_DYN_L2_GAS, 0) }, + { OpCode::LT_8, make_cost(AVM_LT_BASE_L2_GAS, 0, AVM_LT_DYN_L2_GAS, 0) }, + { OpCode::LT_16, make_cost(AVM_LT_BASE_L2_GAS, 0, AVM_LT_DYN_L2_GAS, 0) }, + { OpCode::LTE_8, make_cost(AVM_LTE_BASE_L2_GAS, 0, AVM_LTE_DYN_L2_GAS, 0) }, + { OpCode::LTE_16, make_cost(AVM_LTE_BASE_L2_GAS, 0, AVM_LTE_DYN_L2_GAS, 0) }, + { OpCode::AND_8, make_cost(AVM_AND_BASE_L2_GAS, 0, AVM_AND_DYN_L2_GAS, 0) }, + { OpCode::AND_16, make_cost(AVM_AND_BASE_L2_GAS, 0, AVM_AND_DYN_L2_GAS, 0) }, + { OpCode::OR_8, make_cost(AVM_OR_BASE_L2_GAS, 0, AVM_OR_DYN_L2_GAS, 0) }, + { OpCode::OR_16, make_cost(AVM_OR_BASE_L2_GAS, 0, AVM_OR_DYN_L2_GAS, 0) }, + { OpCode::XOR_8, make_cost(AVM_XOR_BASE_L2_GAS, 0, AVM_XOR_DYN_L2_GAS, 0) }, + { OpCode::XOR_16, make_cost(AVM_XOR_BASE_L2_GAS, 0, AVM_XOR_DYN_L2_GAS, 0) }, { OpCode::NOT, make_cost(AVM_NOT_BASE_L2_GAS, 0, AVM_NOT_DYN_L2_GAS, 0) }, - { OpCode::SHL, make_cost(AVM_SHL_BASE_L2_GAS, 0, AVM_SHL_DYN_L2_GAS, 0) }, - { OpCode::SHR, make_cost(AVM_SHR_BASE_L2_GAS, 0, AVM_SHR_DYN_L2_GAS, 0) }, + { OpCode::SHL_8, make_cost(AVM_SHL_BASE_L2_GAS, 0, AVM_SHL_DYN_L2_GAS, 0) }, + { OpCode::SHL_16, make_cost(AVM_SHL_BASE_L2_GAS, 0, AVM_SHL_DYN_L2_GAS, 0) }, + { OpCode::SHR_8, make_cost(AVM_SHR_BASE_L2_GAS, 0, AVM_SHR_DYN_L2_GAS, 0) }, + { OpCode::SHR_16, make_cost(AVM_SHR_BASE_L2_GAS, 0, AVM_SHR_DYN_L2_GAS, 0) }, { OpCode::CAST, make_cost(AVM_CAST_BASE_L2_GAS, 0, AVM_CAST_DYN_L2_GAS, 0) }, { OpCode::ADDRESS, make_cost(AVM_ADDRESS_BASE_L2_GAS, 0, AVM_ADDRESS_DYN_L2_GAS, 0) }, { OpCode::STORAGEADDRESS, make_cost(AVM_STORAGEADDRESS_BASE_L2_GAS, 0, AVM_STORAGEADDRESS_DYN_L2_GAS, 0) }, @@ -42,20 +55,23 @@ const std::unordered_map GAS_COST_TABLE = { { OpCode::VERSION, make_cost(AVM_VERSION_BASE_L2_GAS, 0, AVM_VERSION_DYN_L2_GAS, 0) }, { OpCode::BLOCKNUMBER, make_cost(AVM_BLOCKNUMBER_BASE_L2_GAS, 0, AVM_BLOCKNUMBER_DYN_L2_GAS, 0) }, { OpCode::TIMESTAMP, make_cost(AVM_TIMESTAMP_BASE_L2_GAS, 0, AVM_TIMESTAMP_DYN_L2_GAS, 0) }, - { OpCode::COINBASE, make_cost(AVM_COINBASE_BASE_L2_GAS, 0, AVM_COINBASE_DYN_L2_GAS, 0) }, { OpCode::FEEPERL2GAS, make_cost(AVM_FEEPERL2GAS_BASE_L2_GAS, 0, AVM_FEEPERL2GAS_DYN_L2_GAS, 0) }, { OpCode::FEEPERDAGAS, make_cost(AVM_FEEPERDAGAS_BASE_L2_GAS, 0, AVM_FEEPERDAGAS_DYN_L2_GAS, 0) }, - { OpCode::BLOCKL2GASLIMIT, make_cost(AVM_BLOCKL2GASLIMIT_BASE_L2_GAS, 0, AVM_BLOCKL2GASLIMIT_DYN_L2_GAS, 0) }, - { OpCode::BLOCKDAGASLIMIT, make_cost(AVM_BLOCKDAGASLIMIT_BASE_L2_GAS, 0, AVM_BLOCKDAGASLIMIT_DYN_L2_GAS, 0) }, { OpCode::CALLDATACOPY, make_cost(AVM_CALLDATACOPY_BASE_L2_GAS, 0, AVM_CALLDATACOPY_DYN_L2_GAS, 0) }, { OpCode::L2GASLEFT, make_cost(AVM_L2GASLEFT_BASE_L2_GAS, 0, AVM_L2GASLEFT_DYN_L2_GAS, 0) }, { OpCode::DAGASLEFT, make_cost(AVM_DAGASLEFT_BASE_L2_GAS, 0, AVM_DAGASLEFT_DYN_L2_GAS, 0) }, - { OpCode::JUMP, make_cost(AVM_JUMP_BASE_L2_GAS, 0, AVM_JUMP_DYN_L2_GAS, 0) }, - { OpCode::JUMPI, make_cost(AVM_JUMPI_BASE_L2_GAS, 0, AVM_JUMPI_DYN_L2_GAS, 0) }, + { OpCode::JUMP_16, make_cost(AVM_JUMP_BASE_L2_GAS, 0, AVM_JUMP_DYN_L2_GAS, 0) }, + { OpCode::JUMPI_16, make_cost(AVM_JUMPI_BASE_L2_GAS, 0, AVM_JUMPI_DYN_L2_GAS, 0) }, { OpCode::INTERNALCALL, make_cost(AVM_INTERNALCALL_BASE_L2_GAS, 0, AVM_INTERNALCALL_DYN_L2_GAS, 0) }, { OpCode::INTERNALRETURN, make_cost(AVM_INTERNALRETURN_BASE_L2_GAS, 0, AVM_INTERNALRETURN_DYN_L2_GAS, 0) }, - { OpCode::SET, make_cost(AVM_SET_BASE_L2_GAS, 0, AVM_SET_DYN_L2_GAS, 0) }, - { OpCode::MOV, make_cost(AVM_MOV_BASE_L2_GAS, 0, AVM_MOV_DYN_L2_GAS, 0) }, + { OpCode::SET_8, make_cost(AVM_SET_BASE_L2_GAS, 0, AVM_SET_DYN_L2_GAS, 0) }, + { OpCode::SET_16, make_cost(AVM_SET_BASE_L2_GAS, 0, AVM_SET_DYN_L2_GAS, 0) }, + { OpCode::SET_32, make_cost(AVM_SET_BASE_L2_GAS, 0, AVM_SET_DYN_L2_GAS, 0) }, + { OpCode::SET_64, make_cost(AVM_SET_BASE_L2_GAS, 0, AVM_SET_DYN_L2_GAS, 0) }, + { OpCode::SET_128, make_cost(AVM_SET_BASE_L2_GAS, 0, AVM_SET_DYN_L2_GAS, 0) }, + { OpCode::SET_FF, make_cost(AVM_SET_BASE_L2_GAS, 0, AVM_SET_DYN_L2_GAS, 0) }, + { OpCode::MOV_8, make_cost(AVM_MOV_BASE_L2_GAS, 0, AVM_MOV_DYN_L2_GAS, 0) }, + { OpCode::MOV_16, make_cost(AVM_MOV_BASE_L2_GAS, 0, AVM_MOV_DYN_L2_GAS, 0) }, { OpCode::CMOV, make_cost(AVM_CMOV_BASE_L2_GAS, 0, AVM_CMOV_DYN_L2_GAS, 0) }, { OpCode::SLOAD, make_cost(AVM_SLOAD_BASE_L2_GAS, 0, AVM_SLOAD_DYN_L2_GAS, 0) }, { OpCode::SSTORE, make_cost(AVM_SSTORE_BASE_L2_GAS, 0, AVM_SSTORE_DYN_L2_GAS, 0) }, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp index 8867608b488..0380178eda8 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp @@ -69,7 +69,7 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx) return false; } - return static_cast((ind_value & (1 << operand_idx)) >> operand_idx); + return (ind_value & (1 << operand_idx)) != 0; } std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/instructions.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/instructions.hpp index 78679099bb0..5c003ece969 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/instructions.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/instructions.hpp @@ -11,7 +11,7 @@ namespace bb::avm_trace { -using Operand = std::variant; +using Operand = std::variant; class Instruction { public: @@ -40,6 +40,8 @@ class Instruction { str += std::to_string(std::get(operand)); } else if (std::holds_alternative(operand)) { str += "someu128"; + } else if (std::holds_alternative(operand)) { + str += "someff"; } else { str += "unknown operand type"; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.cpp index f953f7b8489..d646b2e51b4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.cpp @@ -124,16 +124,6 @@ FF AvmKernelTraceBuilder::op_block_number(uint32_t clk) return perform_kernel_input_lookup(BLOCK_NUMBER_SELECTOR); } -FF AvmKernelTraceBuilder::op_coinbase(uint32_t clk) -{ - KernelTraceEntry entry = { - .clk = clk, - .operation = KernelTraceOpType::COINBASE, - }; - kernel_trace.push_back(entry); - return perform_kernel_input_lookup(COINBASE_SELECTOR); -} - FF AvmKernelTraceBuilder::op_timestamp(uint32_t clk) { KernelTraceEntry entry = { @@ -393,10 +383,6 @@ void AvmKernelTraceBuilder::finalize(std::vector>& main_trace) dest.main_kernel_in_offset = BLOCK_NUMBER_SELECTOR; dest.main_sel_q_kernel_lookup = 1; break; - case KernelTraceOpType::COINBASE: - dest.main_kernel_in_offset = COINBASE_SELECTOR; - dest.main_sel_q_kernel_lookup = 1; - break; case KernelTraceOpType::TIMESTAMP: dest.main_kernel_in_offset = TIMESTAMP_SELECTOR; dest.main_sel_q_kernel_lookup = 1; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.hpp index 773d68bba3f..71a5bb77d79 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/kernel_trace.hpp @@ -24,7 +24,6 @@ class AvmKernelTraceBuilder { CHAIN_ID, VERSION, BLOCK_NUMBER, - COINBASE, TIMESTAMP, FEE_PER_DA_GAS, FEE_PER_L2_GAS, @@ -78,7 +77,6 @@ class AvmKernelTraceBuilder { FF op_chain_id(uint32_t clk); FF op_version(uint32_t clk); FF op_block_number(uint32_t clk); - FF op_coinbase(uint32_t clk); FF op_timestamp(uint32_t clk); // Globals - Gas FF op_fee_per_da_gas(uint32_t clk); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp index 4fcbf7aea51..cbee33a6ddd 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp @@ -25,37 +25,60 @@ std::string to_string(OpCode opcode) { switch (opcode) { // Compute - // Compute - Arithmetic - case OpCode::ADD: - return "ADD"; - case OpCode::SUB: - return "SUB"; - case OpCode::MUL: - return "MUL"; - case OpCode::DIV: - return "DIV"; - case OpCode::FDIV: - return "FDIV"; - // Compute - Comparators - case OpCode::EQ: - return "EQ"; - case OpCode::LT: - return "LT"; - case OpCode::LTE: - return "LTE"; - // Compute - Bitwise - case OpCode::AND: - return "AND"; - case OpCode::OR: - return "OR"; - case OpCode::XOR: - return "XOR"; + case OpCode::ADD_8: + return "ADD_8"; + case OpCode::ADD_16: + return "ADD_16"; + case OpCode::SUB_8: + return "SUB_8"; + case OpCode::SUB_16: + return "SUB_16"; + case OpCode::MUL_8: + return "MUL_8"; + case OpCode::MUL_16: + return "MUL_16"; + case OpCode::DIV_8: + return "DIV_8"; + case OpCode::DIV_16: + return "DIV_16"; + case OpCode::FDIV_8: + return "FDIV_8"; + case OpCode::FDIV_16: + return "FDIV_16"; + case OpCode::EQ_8: + return "EQ_8"; + case OpCode::EQ_16: + return "EQ_16"; + case OpCode::LT_8: + return "LT_8"; + case OpCode::LT_16: + return "LT_16"; + case OpCode::LTE_8: + return "LTE_8"; + case OpCode::LTE_16: + return "LTE_16"; + case OpCode::AND_8: + return "AND_8"; + case OpCode::AND_16: + return "AND_16"; + case OpCode::OR_8: + return "OR_8"; + case OpCode::OR_16: + return "OR_16"; + case OpCode::XOR_8: + return "XOR_8"; + case OpCode::XOR_16: + return "XOR_16"; case OpCode::NOT: return "NOT"; - case OpCode::SHL: - return "SHL"; - case OpCode::SHR: - return "SHR"; + case OpCode::SHL_8: + return "SHL_8"; + case OpCode::SHL_16: + return "SHL_16"; + case OpCode::SHR_8: + return "SHR_8"; + case OpCode::SHR_16: + return "SHR_16"; // Compute - Type Conversions case OpCode::CAST: return "CAST"; @@ -79,16 +102,10 @@ std::string to_string(OpCode opcode) return "BLOCKNUMBER"; case OpCode::TIMESTAMP: return "TIMESTAMP"; - case OpCode::COINBASE: - return "COINBASE"; case OpCode::FEEPERL2GAS: return "FEEPERL2GAS"; case OpCode::FEEPERDAGAS: return "FEEPERDAGAS"; - case OpCode::BLOCKL2GASLIMIT: - return "BLOCKL2GASLIMIT"; - case OpCode::BLOCKDAGASLIMIT: - return "BLOCKDAGASLIMIT"; // Execution Environment - Calldata case OpCode::CALLDATACOPY: return "CALLDATACOPY"; @@ -99,19 +116,31 @@ std::string to_string(OpCode opcode) case OpCode::DAGASLEFT: return "DAGASLEFT"; // Machine State - Internal Control Flow - case OpCode::JUMP: - return "JUMP"; - case OpCode::JUMPI: - return "JUMPI"; + case OpCode::JUMP_16: + return "JUMP_16"; + case OpCode::JUMPI_16: + return "JUMPI_16"; case OpCode::INTERNALCALL: return "INTERNALCALL"; case OpCode::INTERNALRETURN: return "INTERNALRETURN"; // Machine State - Memory - case OpCode::SET: - return "SET"; - case OpCode::MOV: - return "MOV"; + case OpCode::SET_8: + return "SET_8"; + case OpCode::SET_16: + return "SET_16"; + case OpCode::SET_32: + return "SET_32"; + case OpCode::SET_64: + return "SET_64"; + case OpCode::SET_128: + return "SET_128"; + case OpCode::SET_FF: + return "SET_FF"; + case OpCode::MOV_8: + return "MOV_8"; + case OpCode::MOV_16: + return "MOV_16"; case OpCode::CMOV: return "CMOV"; // World State diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp index 885d2020cca..e27931cebf4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp @@ -21,24 +21,33 @@ namespace bb::avm_trace { */ enum class OpCode : uint8_t { // Compute - // Compute - Arithmetic - ADD, - SUB, - MUL, - DIV, - FDIV, - // Compute - Comparators - EQ, - LT, - LTE, - // Compute - Bitwise - AND, - OR, - XOR, + ADD_8, + ADD_16, + SUB_8, + SUB_16, + MUL_8, + MUL_16, + DIV_8, + DIV_16, + FDIV_8, + FDIV_16, + EQ_8, + EQ_16, + LT_8, + LT_16, + LTE_8, + LTE_16, + AND_8, + AND_16, + OR_8, + OR_16, + XOR_8, + XOR_16, NOT, - SHL, - SHR, - // Compute - Type Conversions + SHL_8, + SHL_16, + SHR_8, + SHR_16, CAST, // Execution Environment @@ -52,11 +61,8 @@ enum class OpCode : uint8_t { VERSION, BLOCKNUMBER, TIMESTAMP, - COINBASE, FEEPERL2GAS, FEEPERDAGAS, - BLOCKL2GASLIMIT, - BLOCKDAGASLIMIT, // Execution Environment - Calldata CALLDATACOPY, @@ -65,13 +71,19 @@ enum class OpCode : uint8_t { L2GASLEFT, DAGASLEFT, // Machine State - Internal Control Flow - JUMP, - JUMPI, + JUMP_16, + JUMPI_16, INTERNALCALL, INTERNALRETURN, // Machine State - Memory - SET, - MOV, + SET_8, + SET_16, + SET_32, + SET_64, + SET_128, + SET_FF, + MOV_8, + MOV_16, CMOV, // World State diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index 3dc1d434db8..459f790f8ae 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -217,10 +217,10 @@ FF AvmTraceBuilder::unconstrained_read_from_memory(AddressWithMode addr) void AvmTraceBuilder::write_to_memory(AddressWithMode addr, FF val, AvmMemoryTag w_tag) { - // op_set_internal increments the pc, so we need to store the current pc and then jump back to it + // op_set increments the pc, so we need to store the current pc and then jump back to it // to legaly reset the pc. auto current_pc = pc; - op_set_internal(static_cast(addr.mode), val, addr.offset, w_tag); + op_set(static_cast(addr.mode), val, addr.offset, w_tag); op_jump(current_pc); } @@ -322,7 +322,7 @@ void AvmTraceBuilder::op_add( auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::ADD); + gas_trace_builder.constrain_gas(clk, OpCode::ADD_8); main_trace.push_back(Row{ .main_clk = clk, @@ -389,7 +389,7 @@ void AvmTraceBuilder::op_sub( auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::SUB); + gas_trace_builder.constrain_gas(clk, OpCode::SUB_8); main_trace.push_back(Row{ .main_clk = clk, @@ -456,7 +456,7 @@ void AvmTraceBuilder::op_mul( auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::MUL); + gas_trace_builder.constrain_gas(clk, OpCode::MUL_8); main_trace.push_back(Row{ .main_clk = clk, @@ -534,7 +534,7 @@ void AvmTraceBuilder::op_div( auto write_dst = constrained_write_to_memory(call_ptr, clk, resolved_dst, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::DIV); + gas_trace_builder.constrain_gas(clk, OpCode::DIV_8); main_trace.push_back(Row{ .main_clk = clk, @@ -576,7 +576,8 @@ void AvmTraceBuilder::op_div( * @param dst_offset An index in memory pointing to the output of the division. * @param in_tag The instruction memory tag of the operands. */ -void AvmTraceBuilder::op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset) +void AvmTraceBuilder::op_fdiv( + uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, [[maybe_unused]] AvmMemoryTag in_tag) { auto clk = static_cast(main_trace.size()) + 1; @@ -614,7 +615,7 @@ void AvmTraceBuilder::op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_of call_ptr, clk, resolved_c, c, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::FDIV); + gas_trace_builder.constrain_gas(clk, OpCode::FDIV_8); main_trace.push_back(Row{ .main_clk = clk, @@ -684,7 +685,7 @@ void AvmTraceBuilder::op_eq( constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, AvmMemoryTag::U8, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::EQ); + gas_trace_builder.constrain_gas(clk, OpCode::EQ_8); main_trace.push_back(Row{ .main_clk = clk, @@ -736,7 +737,7 @@ void AvmTraceBuilder::op_lt( constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, AvmMemoryTag::U8, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::LT); + gas_trace_builder.constrain_gas(clk, OpCode::LT_8); main_trace.push_back(Row{ .main_clk = clk, @@ -789,7 +790,7 @@ void AvmTraceBuilder::op_lte( constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, AvmMemoryTag::U8, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::LTE); + gas_trace_builder.constrain_gas(clk, OpCode::LTE_8); main_trace.push_back(Row{ .main_clk = clk, @@ -845,7 +846,7 @@ void AvmTraceBuilder::op_and( auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::AND); + gas_trace_builder.constrain_gas(clk, OpCode::AND_8); main_trace.push_back(Row{ .main_clk = clk, @@ -897,7 +898,7 @@ void AvmTraceBuilder::op_or( auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::OR); + gas_trace_builder.constrain_gas(clk, OpCode::OR_8); main_trace.push_back(Row{ .main_clk = clk, @@ -950,7 +951,7 @@ void AvmTraceBuilder::op_xor( auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::XOR); + gas_trace_builder.constrain_gas(clk, OpCode::XOR_8); main_trace.push_back(Row{ .main_clk = clk, @@ -1059,7 +1060,7 @@ void AvmTraceBuilder::op_shl( // Write into memory value c from intermediate register ic. auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::SHL); + gas_trace_builder.constrain_gas(clk, OpCode::SHL_8); main_trace.push_back(Row{ .main_clk = clk, @@ -1111,7 +1112,7 @@ void AvmTraceBuilder::op_shr( // Write into memory value c from intermediate register ic. auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::SHR); + gas_trace_builder.constrain_gas(clk, OpCode::SHR_8); main_trace.push_back(Row{ .main_clk = clk, @@ -1381,19 +1382,6 @@ void AvmTraceBuilder::op_timestamp(uint8_t indirect, uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_coinbase(uint8_t indirect, uint32_t dst_offset) -{ - auto const clk = static_cast(main_trace.size()) + 1; - FF ia_value = kernel_trace_builder.op_coinbase(clk); - Row row = create_kernel_lookup_opcode(indirect, dst_offset, ia_value, AvmMemoryTag::FF); - row.main_sel_op_coinbase = FF(1); - - // Constrain gas cost - gas_trace_builder.constrain_gas(static_cast(row.main_clk), OpCode::COINBASE); - - main_trace.push_back(row); -} - void AvmTraceBuilder::op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset) { auto const clk = static_cast(main_trace.size()) + 1; @@ -1438,14 +1426,20 @@ void AvmTraceBuilder::op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset) * than call_data_mem.size() * * @param indirect A byte encoding information about indirect/direct memory access. - * @param cd_offset The starting index of the region in calldata to be copied. - * @param copy_size The number of finite field elements to be copied into memory. + * @param cd_offset_address The starting index of the region in calldata to be copied. + * @param copy_size_offset The number of finite field elements to be copied into memory. * @param dst_offset The starting index of memory where calldata will be copied to. */ -void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset) +void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, + uint32_t cd_offset_address, + uint32_t copy_size_address, + uint32_t dst_offset) { auto clk = static_cast(main_trace.size()) + 1; + auto [cd_offset_address_r, copy_size_address_r, _] = + unpack_indirects<3>(indirect, { cd_offset_address, copy_size_address, dst_offset }); + uint32_t direct_dst_offset = dst_offset; // Will be overwritten in indirect mode. bool indirect_flag = false; @@ -1455,7 +1449,7 @@ void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uin // direct destination offset stored in main_mem_addr_c. // All the other memory operations are triggered by the slice gadget. - if (is_operand_indirect(indirect, 0)) { + if (is_operand_indirect(indirect, 2)) { indirect_flag = true; auto ind_read = mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_C, dst_offset); @@ -1463,6 +1457,10 @@ void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uin tag_match = ind_read.tag_match; } + // TODO: constrain these. + const uint32_t cd_offset = static_cast(unconstrained_read_from_memory(cd_offset_address_r)); + const uint32_t copy_size = static_cast(unconstrained_read_from_memory(copy_size_address_r)); + if (tag_match) { slice_trace_builder.create_calldata_copy_slice( calldata, clk, call_ptr, cd_offset, copy_size, direct_dst_offset); @@ -1566,7 +1564,7 @@ void AvmTraceBuilder::op_jump(uint32_t jmp_dest) auto clk = static_cast(main_trace.size()) + 1; // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::JUMP); + gas_trace_builder.constrain_gas(clk, OpCode::JUMP_16); main_trace.push_back(Row{ .main_clk = clk, @@ -1615,7 +1613,7 @@ void AvmTraceBuilder::op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t con uint32_t next_pc = !id_zero ? jmp_dest : pc + 1; // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::JUMPI); + gas_trace_builder.constrain_gas(clk, OpCode::JUMPI_16); main_trace.push_back(Row{ .main_clk = clk, @@ -1747,13 +1745,7 @@ void AvmTraceBuilder::op_internal_return() * @param dst_offset Memory destination offset where val is written to * @param in_tag The instruction memory tag */ -void AvmTraceBuilder::op_set(uint8_t indirect, uint128_t val, uint32_t dst_offset, AvmMemoryTag in_tag) -{ - auto const val_ff = FF{ uint256_t::from_uint128(val) }; - op_set_internal(indirect, val_ff, dst_offset, in_tag); -} - -void AvmTraceBuilder::op_set_internal(uint8_t indirect, FF val_ff, uint32_t dst_offset, AvmMemoryTag in_tag) +void AvmTraceBuilder::op_set(uint8_t indirect, FF val_ff, uint32_t dst_offset, AvmMemoryTag in_tag) { auto const clk = static_cast(main_trace.size()) + 1; auto [resolved_c] = unpack_indirects<1>(indirect, { dst_offset }); @@ -1762,7 +1754,8 @@ void AvmTraceBuilder::op_set_internal(uint8_t indirect, FF val_ff, uint32_t dst_ constrained_write_to_memory(call_ptr, clk, resolved_c, val_ff, AvmMemoryTag::U0, in_tag, IntermRegister::IC); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::SET); + // FIXME: not great that we are having to choose one specific opcode here! + gas_trace_builder.constrain_gas(clk, OpCode::SET_8); main_trace.push_back(Row{ .main_clk = clk, @@ -1820,7 +1813,8 @@ void AvmTraceBuilder::op_mov(uint8_t indirect, uint32_t src_offset, uint32_t dst mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, direct_dst_offset, val, tag, tag); // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::MOV); + // FIXME: not great that we are having to choose one specific opcode here! + gas_trace_builder.constrain_gas(clk, OpCode::MOV_8); main_trace.push_back(Row{ .main_clk = clk, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp index a301b637b73..873d58210db 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp @@ -64,7 +64,7 @@ class AvmTraceBuilder { void op_sub(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); void op_mul(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); void op_div(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - void op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset); + void op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); // Compute - Comparators void op_eq(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); @@ -94,12 +94,11 @@ class AvmTraceBuilder { void op_version(uint8_t indirect, uint32_t dst_offset); void op_block_number(uint8_t indirect, uint32_t dst_offset); void op_timestamp(uint8_t indirect, uint32_t dst_offset); - void op_coinbase(uint8_t indirect, uint32_t dst_offset); void op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset); void op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset); // Execution Environment - Calldata - void op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset); + void op_calldata_copy(uint8_t indirect, uint32_t cd_offset_address, uint32_t copy_size_offset, uint32_t dst_offset); // Machine State - Gas void op_l2gasleft(uint8_t indirect, uint32_t dst_offset); @@ -113,9 +112,7 @@ class AvmTraceBuilder { void op_internal_return(); // Machine State - Memory - void op_set(uint8_t indirect, uint128_t val, uint32_t dst_offset, AvmMemoryTag in_tag); - // TODO: only used for write_slice_to_memory. Remove. - void op_set_internal(uint8_t indirect, FF val_ff, uint32_t dst_offset, AvmMemoryTag in_tag); + void op_set(uint8_t indirect, FF val, uint32_t dst_offset, AvmMemoryTag in_tag); void op_mov(uint8_t indirect, uint32_t src_offset, uint32_t dst_offset); void op_cmov(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t cond_offset, uint32_t dst_offset); diff --git a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp index 919d02fae1d..68c5ce65516 100644 --- a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp @@ -43,7 +43,6 @@ #define VERSION_SELECTOR 30 #define BLOCK_NUMBER_SELECTOR 31 #define TIMESTAMP_SELECTOR 33 -#define COINBASE_SELECTOR 34 #define FEE_PER_DA_GAS_SELECTOR 36 #define FEE_PER_L2_GAS_SELECTOR 37 #define END_GLOBAL_VARIABLES 38 @@ -85,11 +84,8 @@ #define AVM_VERSION_BASE_L2_GAS 200 #define AVM_BLOCKNUMBER_BASE_L2_GAS 200 #define AVM_TIMESTAMP_BASE_L2_GAS 200 -#define AVM_COINBASE_BASE_L2_GAS 200 #define AVM_FEEPERL2GAS_BASE_L2_GAS 200 #define AVM_FEEPERDAGAS_BASE_L2_GAS 200 -#define AVM_BLOCKL2GASLIMIT_BASE_L2_GAS 200 -#define AVM_BLOCKDAGASLIMIT_BASE_L2_GAS 200 #define AVM_CALLDATACOPY_BASE_L2_GAS 290 #define AVM_L2GASLEFT_BASE_L2_GAS 180 #define AVM_DAGASLEFT_BASE_L2_GAS 180 @@ -150,11 +146,8 @@ #define AVM_VERSION_DYN_L2_GAS 0 #define AVM_BLOCKNUMBER_DYN_L2_GAS 0 #define AVM_TIMESTAMP_DYN_L2_GAS 0 -#define AVM_COINBASE_DYN_L2_GAS 0 #define AVM_FEEPERL2GAS_DYN_L2_GAS 0 #define AVM_FEEPERDAGAS_DYN_L2_GAS 0 -#define AVM_BLOCKL2GASLIMIT_DYN_L2_GAS 0 -#define AVM_BLOCKDAGASLIMIT_DYN_L2_GAS 0 #define AVM_CALLDATACOPY_DYN_L2_GAS 50 #define AVM_L2GASLEFT_DYN_L2_GAS 0 #define AVM_DAGASLEFT_DYN_L2_GAS 0 diff --git a/barretenberg/cpp/src/barretenberg/vm/constants.hpp b/barretenberg/cpp/src/barretenberg/vm/constants.hpp index ec2f0e9ac7f..c7024d89587 100644 --- a/barretenberg/cpp/src/barretenberg/vm/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/constants.hpp @@ -26,7 +26,6 @@ inline const uint32_t CHAIN_ID_OFFSET = PCPI_GLOBALS_START; inline const uint32_t VERSION_OFFSET = PCPI_GLOBALS_START + 1; inline const uint32_t BLOCK_NUMBER_OFFSET = PCPI_GLOBALS_START + 2; inline const uint32_t TIMESTAMP_OFFSET = PCPI_GLOBALS_START + 3; -inline const uint32_t COINBASE_OFFSET = PCPI_GLOBALS_START + 4; // Global Variables - fees inline const uint32_t FEE_PER_DA_GAS_OFFSET = PCPI_GLOBALS_START + 6; inline const uint32_t FEE_PER_L2_GAS_OFFSET = PCPI_GLOBALS_START + 7; diff --git a/barretenberg/sol/src/honk/Fr.sol b/barretenberg/sol/src/honk/Fr.sol index 26fada6693a..aeeebb0f2ad 100644 --- a/barretenberg/sol/src/honk/Fr.sol +++ b/barretenberg/sol/src/honk/Fr.sol @@ -13,8 +13,9 @@ using {notEqual as !=} for Fr global; using {equal as ==} for Fr global; uint256 constant MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order - +Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1); // Instantiation + library FrLib { function from(uint256 value) internal pure returns (Fr) { return Fr.wrap(value % MODULUS); @@ -79,7 +80,6 @@ library FrLib { // TODO: Montgomery's batch inversion trick function div(Fr numerator, Fr denominator) internal view returns (Fr) { - Fr inversion = invert(denominator); return numerator * invert(denominator); } } diff --git a/barretenberg/sol/src/honk/HonkTypes.sol b/barretenberg/sol/src/honk/HonkTypes.sol index 275c26ab7f2..593d4bf2c2a 100644 --- a/barretenberg/sol/src/honk/HonkTypes.sol +++ b/barretenberg/sol/src/honk/HonkTypes.sol @@ -8,14 +8,14 @@ import {Fr} from "./Fr.sol"; uint256 constant CONST_PROOF_SIZE_LOG_N = 28; -uint256 constant NUMBER_OF_SUBRELATIONS = 18; -uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 7; -uint256 constant NUMBER_OF_ENTITIES = 42; -uint256 constant NUMBER_OF_ALPHAS = 17; +uint256 constant NUMBER_OF_SUBRELATIONS = 26; +uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8; +uint256 constant NUMBER_OF_ENTITIES = 44; +uint256 constant NUMBER_UNSHIFTED = 35; +uint256 constant NUMBER_TO_BE_SHIFTED = 9; -// Prime field order -uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order -uint256 constant P = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order +// Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1 +uint256 constant NUMBER_OF_ALPHAS = 25; // ENUM FOR WIRES enum WIRE { @@ -30,6 +30,8 @@ enum WIRE { Q_ELLIPTIC, Q_AUX, Q_LOOKUP, + Q_POSEIDON2_EXTERNAL, + Q_POSEIDON2_INTERNAL, SIGMA_1, SIGMA_2, SIGMA_3, @@ -94,6 +96,8 @@ library Honk { G1Point qAux; // Auxillary G1Point qElliptic; // Auxillary G1Point qLookup; // Lookup + G1Point qPoseidon2External; + G1Point qPoseidon2Internal; // Copy cnstraints G1Point s1; G1Point s2; diff --git a/barretenberg/sol/src/honk/HonkVerifier.sol b/barretenberg/sol/src/honk/HonkVerifier.sol index 942adc6814f..540398bc0c6 100644 --- a/barretenberg/sol/src/honk/HonkVerifier.sol +++ b/barretenberg/sol/src/honk/HonkVerifier.sol @@ -11,19 +11,20 @@ import { NUMBER_OF_ENTITIES, NUMBER_OF_SUBRELATIONS, NUMBER_OF_ALPHAS, + NUMBER_UNSHIFTED, BATCHED_RELATION_PARTIAL_LENGTH, - CONST_PROOF_SIZE_LOG_N, - P, - Q + CONST_PROOF_SIZE_LOG_N } from "./HonkTypes.sol"; import {ecMul, ecAdd, ecSub, negateInplace, convertProofPoint} from "./utils.sol"; // Field arithmetic libraries - prevent littering the code with modmul / addmul -import {Fr, FrLib} from "./Fr.sol"; +import {MODULUS as P, MINUS_ONE, Fr, FrLib} from "./Fr.sol"; // Transcript library to generate fiat shamir challenges import {Transcript, TranscriptLib} from "./Transcript.sol"; +import {RelationsLib} from "./Relations.sol"; + error PublicInputsLengthWrong(); error SumcheckFailed(); error ZeromorphFailed(); @@ -34,14 +35,14 @@ abstract contract BaseHonkVerifier is IVerifier { function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) { Honk.VerificationKey memory vk = loadVerificationKey(); - Honk.Proof memory p = loadProof(proof); + Honk.Proof memory p = TranscriptLib.loadProof(proof); if (publicInputs.length != vk.publicInputsSize) { revert PublicInputsLengthWrong(); } // Generate the fiat shamir challenges for the whole protocol - Transcript memory t = TranscriptLib.generateTranscript(p, vk, publicInputs); + Transcript memory t = TranscriptLib.generateTranscript(p, publicInputs, vk.publicInputsSize); // Compute the public input delta t.publicInputsDelta = @@ -62,138 +63,6 @@ abstract contract BaseHonkVerifier is IVerifier { return VK.loadVerificationKey(); } - // TODO: mod q proof points - // TODO: Preprocess all of the memory locations - // TODO: Adjust proof point serde away from poseidon forced field elements - function loadProof(bytes calldata proof) internal view returns (Honk.Proof memory) { - Honk.Proof memory p; - - // Metadata - p.circuitSize = uint256(bytes32(proof[0x00:0x20])); - p.publicInputsSize = uint256(bytes32(proof[0x20:0x40])); - p.publicInputsOffset = uint256(bytes32(proof[0x40:0x60])); - - // Commitments - p.w1 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x60:0x80])), - x_1: uint256(bytes32(proof[0x80:0xa0])), - y_0: uint256(bytes32(proof[0xa0:0xc0])), - y_1: uint256(bytes32(proof[0xc0:0xe0])) - }); - - p.w2 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0xe0:0x100])), - x_1: uint256(bytes32(proof[0x100:0x120])), - y_0: uint256(bytes32(proof[0x120:0x140])), - y_1: uint256(bytes32(proof[0x140:0x160])) - }); - p.w3 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x160:0x180])), - x_1: uint256(bytes32(proof[0x180:0x1a0])), - y_0: uint256(bytes32(proof[0x1a0:0x1c0])), - y_1: uint256(bytes32(proof[0x1c0:0x1e0])) - }); - - // Lookup / Permutation Helper Commitments - p.lookupReadCounts = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x1e0:0x200])), - x_1: uint256(bytes32(proof[0x200:0x220])), - y_0: uint256(bytes32(proof[0x220:0x240])), - y_1: uint256(bytes32(proof[0x240:0x260])) - }); - p.lookupReadTags = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x260:0x280])), - x_1: uint256(bytes32(proof[0x280:0x2a0])), - y_0: uint256(bytes32(proof[0x2a0:0x2c0])), - y_1: uint256(bytes32(proof[0x2c0:0x2e0])) - }); - p.w4 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x2e0:0x300])), - x_1: uint256(bytes32(proof[0x300:0x320])), - y_0: uint256(bytes32(proof[0x320:0x340])), - y_1: uint256(bytes32(proof[0x340:0x360])) - }); - p.lookupInverses = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x360:0x380])), - x_1: uint256(bytes32(proof[0x380:0x3a0])), - y_0: uint256(bytes32(proof[0x3a0:0x3c0])), - y_1: uint256(bytes32(proof[0x3c0:0x3e0])) - }); - p.zPerm = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x3e0:0x400])), - x_1: uint256(bytes32(proof[0x400:0x420])), - y_0: uint256(bytes32(proof[0x420:0x440])), - y_1: uint256(bytes32(proof[0x440:0x460])) - }); - - // TEMP the boundary of what has already been read - uint256 boundary = 0x460; - - // Sumcheck univariates - // TODO: in this case we know what log_n is - so we hard code it, we would want this to be included in - // a cpp template for different circuit sizes - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - // The loop boundary of i, this will shift forward on each evaluation - uint256 loop_boundary = boundary + (i * 0x20 * BATCHED_RELATION_PARTIAL_LENGTH); - - for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { - uint256 start = loop_boundary + (j * 0x20); - uint256 end = start + 0x20; - p.sumcheckUnivariates[i][j] = FrLib.fromBytes32(bytes32(proof[start:end])); - } - } - - boundary = boundary + (CONST_PROOF_SIZE_LOG_N * BATCHED_RELATION_PARTIAL_LENGTH * 0x20); - // Sumcheck evaluations - for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { - uint256 start = boundary + (i * 0x20); - uint256 end = start + 0x20; - p.sumcheckEvaluations[i] = FrLib.fromBytes32(bytes32(proof[start:end])); - } - - boundary = boundary + (NUMBER_OF_ENTITIES * 0x20); - // Zero morph Commitments - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - // Explicitly stating the x0, x1, y0, y1 start and end boundaries to make the calldata slicing bearable - uint256 xStart = boundary + (i * 0x80); - uint256 xEnd = xStart + 0x20; - - uint256 x1Start = xEnd; - uint256 x1End = x1Start + 0x20; - - uint256 yStart = x1End; - uint256 yEnd = yStart + 0x20; - - uint256 y1Start = yEnd; - uint256 y1End = y1Start + 0x20; - - p.zmCqs[i] = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[xStart:xEnd])), - x_1: uint256(bytes32(proof[x1Start:x1End])), - y_0: uint256(bytes32(proof[yStart:yEnd])), - y_1: uint256(bytes32(proof[y1Start:y1End])) - }); - } - - boundary = boundary + (CONST_PROOF_SIZE_LOG_N * 0x80); - - p.zmCq = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[boundary:boundary + 0x20])), - x_1: uint256(bytes32(proof[boundary + 0x20:boundary + 0x40])), - y_0: uint256(bytes32(proof[boundary + 0x40:boundary + 0x60])), - y_1: uint256(bytes32(proof[boundary + 0x60:boundary + 0x80])) - }); - - p.zmPi = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[boundary + 0x80:boundary + 0xa0])), - x_1: uint256(bytes32(proof[boundary + 0xa0:boundary + 0xc0])), - y_0: uint256(bytes32(proof[boundary + 0xc0:boundary + 0xe0])), - y_1: uint256(bytes32(proof[boundary + 0xe0:boundary + 0x100])) - }); - - return p; - } - function computePublicInputDelta( bytes32[] memory publicInputs, Fr beta, @@ -243,7 +112,7 @@ abstract contract BaseHonkVerifier is IVerifier { } // Last round - Fr grandHonkRelationSum = accumulateRelationEvaluations(proof, tp, powPartialEvaluation); + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations(proof, tp, powPartialEvaluation); verified = (grandHonkRelationSum == roundTarget); } @@ -263,18 +132,27 @@ abstract contract BaseHonkVerifier is IVerifier { returns (Fr targetSum) { // TODO: inline - Fr[7] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000002d0), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff89), - Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000030), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffdd), - Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000030), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff89), - Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000002d0) + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff11), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000090), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff71), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000000f0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000013b0) ]; - Fr[7] memory BARYCENTRIC_DOMAIN = - [Fr.wrap(0x00), Fr.wrap(0x01), Fr.wrap(0x02), Fr.wrap(0x03), Fr.wrap(0x04), Fr.wrap(0x05), Fr.wrap(0x06)]; + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_DOMAIN = [ + Fr.wrap(0x00), + Fr.wrap(0x01), + Fr.wrap(0x02), + Fr.wrap(0x03), + Fr.wrap(0x04), + Fr.wrap(0x05), + Fr.wrap(0x06), + Fr.wrap(0x07) + ]; // To compute the next target sum, we evaluate the given univariate at a point u (challenge). // TODO: opt: use same array mem for each iteratioon @@ -307,590 +185,13 @@ abstract contract BaseHonkVerifier is IVerifier { // Univariate evaluation of the monomial ((1-X_l) + X_l.B_l) at the challenge point X_l=u_l function partiallyEvaluatePOW(Transcript memory tp, Fr currentEvaluation, Fr roundChallenge, uint256 round) internal - view + pure returns (Fr newEvaluation) { Fr univariateEval = Fr.wrap(1) + (roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); newEvaluation = currentEvaluation * univariateEval; } - // Calculate the contributions of each relation to the expected value of the full honk relation - // - // For each relation, we use the purported values ( the ones provided by the prover ) of the multivariates to - // calculate a contribution to the purported value of the full Honk relation. - // These are stored in the evaluations part of the proof object. - // We add these together, with the appropiate scaling factor ( the alphas calculated in challenges ) - // This value is checked against the final value of the target total sum - et voila! - function accumulateRelationEvaluations(Honk.Proof memory proof, Transcript memory tp, Fr powPartialEval) - internal - view - returns (Fr accumulator) - { - Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations = proof.sumcheckEvaluations; - Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; - - // Accumulate all 6 custom gates - each with varying number of subrelations - accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); - accumulatePermutationRelation(purportedEvaluations, tp, evaluations, powPartialEval); - accumulateLogDerivativeLookupRelation(purportedEvaluations, tp, evaluations, powPartialEval); - accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); - accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); - accumulateAuxillaryRelation(purportedEvaluations, tp, evaluations, powPartialEval); - - // Apply alpha challenges to challenge evaluations - // Returns grand honk realtion evaluation - accumulator = scaleAndBatchSubrelations(evaluations, tp.alphas); - } - - /** - * WIRE - * - * Wire is an aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids - * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code - * editors, and thus is noisy. - */ - function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { - return p[uint256(_wire)]; - } - - /** - * Ultra Arithmetic Relation - * - */ - function accumulateArithmeticRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - // Relation 0 - Fr q_arith = wire(p, WIRE.Q_ARITH); - { - Fr neg_half = Fr.wrap(0) - (FrLib.invert(Fr.wrap(2))); - - Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; - accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) - + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); - accum = accum + (q_arith - Fr.wrap(1)) * wire(p, WIRE.W_4_SHIFT); - accum = accum * q_arith; - accum = accum * domainSep; - evals[0] = accum; - } - - // Relation 1 - { - Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); - accum = accum * (q_arith - Fr.wrap(2)); - accum = accum * (q_arith - Fr.wrap(1)); - accum = accum * q_arith; - accum = accum * domainSep; - evals[1] = accum; - } - } - - function accumulatePermutationRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr grand_product_numerator; - Fr grand_product_denominator; - - { - Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * tp.beta + tp.gamma; - num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * tp.beta + tp.gamma); - num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * tp.beta + tp.gamma); - num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * tp.beta + tp.gamma); - - grand_product_numerator = num; - } - { - Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * tp.beta + tp.gamma; - den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * tp.beta + tp.gamma); - den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * tp.beta + tp.gamma); - den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * tp.beta + tp.gamma); - - grand_product_denominator = den; - } - - // Contribution 2 - { - Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; - - acc = acc - - ( - (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * tp.publicInputsDelta)) - * grand_product_denominator - ); - acc = acc * domainSep; - evals[2] = acc; - } - - // Contribution 3 - { - Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; - evals[3] = acc; - } - } - - function accumulateLogDerivativeLookupRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr write_term; - Fr read_term; - - // Calculate the write term (the table accumulation) - { - write_term = wire(p, WIRE.TABLE_1) + tp.gamma + (wire(p, WIRE.TABLE_2) * tp.eta) - + (wire(p, WIRE.TABLE_3) * tp.etaTwo) + (wire(p, WIRE.TABLE_4) * tp.etaThree); - } - - // Calculate the write term - { - Fr derived_entry_1 = wire(p, WIRE.W_L) + tp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); - Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); - Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); - - read_term = derived_entry_1 + (derived_entry_2 * tp.eta) + (derived_entry_3 * tp.etaTwo) - + (wire(p, WIRE.Q_O) * tp.etaThree); - } - - Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; - Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; - - Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) - - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); - - // Inverse calculated correctly relation - Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; - accumulatorNone = accumulatorNone * domainSep; - - // Inverse - Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; - - evals[4] = accumulatorNone; - evals[5] = accumulatorOne; - } - - function accumulateDeltaRangeRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr minus_one = Fr.wrap(0) - Fr.wrap(1); - Fr minus_two = Fr.wrap(0) - Fr.wrap(2); - Fr minus_three = Fr.wrap(0) - Fr.wrap(3); - - // Compute wire differences - Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); - Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); - Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); - Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); - - // Contribution 6 - { - Fr acc = delta_1; - acc = acc * (delta_1 + minus_one); - acc = acc * (delta_1 + minus_two); - acc = acc * (delta_1 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[6] = acc; - } - - // Contribution 7 - { - Fr acc = delta_2; - acc = acc * (delta_2 + minus_one); - acc = acc * (delta_2 + minus_two); - acc = acc * (delta_2 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[7] = acc; - } - - // Contribution 8 - { - Fr acc = delta_3; - acc = acc * (delta_3 + minus_one); - acc = acc * (delta_3 + minus_two); - acc = acc * (delta_3 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[8] = acc; - } - - // Contribution 9 - { - Fr acc = delta_4; - acc = acc * (delta_4 + minus_one); - acc = acc * (delta_4 + minus_two); - acc = acc * (delta_4 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[9] = acc; - } - } - - struct EllipticParams { - // Points - Fr x_1; - Fr y_1; - Fr x_2; - Fr y_2; - Fr y_3; - Fr x_3; - // push accumulators into memory - Fr x_double_identity; - } - - function accumulateEllipticRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - EllipticParams memory ep; - ep.x_1 = wire(p, WIRE.W_R); - ep.y_1 = wire(p, WIRE.W_O); - - ep.x_2 = wire(p, WIRE.W_L_SHIFT); - ep.y_2 = wire(p, WIRE.W_4_SHIFT); - ep.y_3 = wire(p, WIRE.W_O_SHIFT); - ep.x_3 = wire(p, WIRE.W_R_SHIFT); - - Fr q_sign = wire(p, WIRE.Q_L); - Fr q_is_double = wire(p, WIRE.Q_M); - - // Contribution 10 point addition, x-coordinate check - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - Fr x_diff = (ep.x_2 - ep.x_1); - Fr y1_sqr = (ep.y_1 * ep.y_1); - { - // Move to top - Fr partialEval = domainSep; - - Fr y2_sqr = (ep.y_2 * ep.y_2); - Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; - Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); - x_add_identity = x_add_identity * x_diff * x_diff; - x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; - - evals[10] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (Fr.wrap(1) - q_is_double); - } - - // Contribution 11 point addition, x-coordinate check - // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 - { - Fr y1_plus_y3 = ep.y_1 + ep.y_3; - Fr y_diff = ep.y_2 * q_sign - ep.y_1; - Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; - evals[11] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (Fr.wrap(1) - q_is_double); - } - - // Contribution 10 point doubling, x-coordinate check - // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 - // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 - { - Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; - Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; - y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; - Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); - - // NOTE: pushed into memory (stack >:'( ) - ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; - - Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; - evals[10] = evals[10] + acc; - } - - // Contribution 11 point doubling, y-coordinate check - // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 - { - Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; - Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); - evals[11] = evals[11] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; - } - } - - // Constants for the auxiliary relation - Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); - Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); - Fr constant MINUS_ONE = Fr.wrap(P - 1); - - // Parameters used within the Auxiliary Relation - // A struct is used to work around stack too deep. This relation has alot of variables - struct AuxParams { - Fr limb_subproduct; - Fr non_native_field_gate_1; - Fr non_native_field_gate_2; - Fr non_native_field_gate_3; - Fr limb_accumulator_1; - Fr limb_accumulator_2; - Fr memory_record_check; - Fr partial_record_check; - Fr next_gate_access_type; - Fr record_delta; - Fr index_delta; - Fr adjacent_values_match_if_adjacent_indices_match; - Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; - Fr access_check; - Fr next_gate_access_type_is_boolean; - Fr ROM_consistency_check_identity; - Fr RAM_consistency_check_identity; - Fr timestamp_delta; - Fr RAM_timestamp_check_identity; - Fr memory_identity; - Fr index_is_monotonically_increasing; - Fr auxiliary_identity; - } - - function accumulateAuxillaryRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal pure { - AuxParams memory ap; - - /** - * Contribution 12 - * Non native field arithmetic gate 2 - * deg 4 - * - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - * - */ - ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); - ap.non_native_field_gate_2 = - (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); - - ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; - ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); - ap.non_native_field_gate_1 = ap.limb_subproduct; - ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); - ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); - - ap.non_native_field_gate_3 = ap.limb_subproduct; - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); - - Fr non_native_field_identity = - ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; - non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); - - // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm - // deg 2 - ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); - ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); - - // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm - // deg 2 - ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); - ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); - - Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; - limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 - - /** - * MEMORY - * - * A RAM memory record contains a tuple of the following fields: - * * i: `index` of memory cell being accessed - * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) - * * v: `value` of memory cell being accessed - * * a: `access` type of record. read: 0 = read, 1 = write - * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three - * - * A ROM memory record contains a tuple of the following fields: - * * i: `index` of memory cell being accessed - * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) - * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) - * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three - * - * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + - * selectors, depending on whether the gate is a RAM read/write or a ROM read - * - * | gate type | i | v2/t | v | a | r | - * | --------- | -- | ----- | -- | -- | -- | - * | ROM | w1 | w2 | w3 | -- | w4 | - * | RAM | w1 | w2 | w3 | qc | w4 | - * - * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on - * `w2` to fix its value) - * - * - */ - - /** - * Memory Record Check - * Partial degree: 1 - * Total degree: 4 - * - * A ROM/ROM access gate can be evaluated with the identity: - * - * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 - * - * For ROM gates, qc = 0 - */ - ap.memory_record_check = wire(p, WIRE.W_O) * tp.etaThree; - ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * tp.etaTwo); - ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * tp.eta); - ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); - ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 - ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); - - /** - * Contribution 13 & 14 - * ROM Consistency Check - * Partial degree: 1 - * Total degree: 4 - * - * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of - * records that are sorted. - * - * We apply the following checks for the sorted records: - * - * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 - * 2. index values for adjacent records are monotonically increasing - * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} - * - */ - ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); - ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); - - ap.index_is_monotonically_increasing = ap.index_delta * ap.index_delta - ap.index_delta; // deg 2 - - ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + Fr.wrap(1)) * ap.record_delta; // deg 2 - - evals[13] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) - * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 - evals[14] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) - * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 - - ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 - - /** - * Contributions 15,16,17 - * RAM Consistency Check - * - * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` - * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. - * This is validated by requiring `access` to be boolean - * - * For two adjacent entries in the sorted list if _both_ - * A) index values match - * B) adjacent access value is 0 (i.e. next gate is a READ) - * then - * C) both values must match. - * The gate boolean check is - * (A && B) => C === !(A && B) || C === !A || !B || C - * - * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized - * with a WRITE operation. - */ - Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 - ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 - - // TODO(https://github.com/AztecProtocol/barretenberg/issues/757): If we sorted in - // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta - // deg 1 or 4 - ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * tp.etaThree; - ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * tp.etaTwo); - ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * tp.eta); - ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; - - Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); - ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = ( - ap.index_delta * MINUS_ONE + Fr.wrap(1) - ) * value_delta * (ap.next_gate_access_type * MINUS_ONE + Fr.wrap(1)); // deg 3 or 6 - - // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the - // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't - // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access - // type is correct, to cover this edge case - // deg 2 or 4 - ap.next_gate_access_type_is_boolean = - ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; - - // Putting it all together... - evals[15] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation - * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 or 8 - evals[16] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 - evals[17] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 6 - - ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9 - - /** - * RAM Timestamp Consistency Check - * - * | w1 | w2 | w3 | w4 | - * | index | timestamp | timestamp_check | -- | - * - * Let delta_index = index_{i + 1} - index_{i} - * - * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i - * Else timestamp_check = 0 - */ - ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); - ap.RAM_timestamp_check_identity = - (ap.index_delta * MINUS_ONE + Fr.wrap(1)) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 - - /** - * Complete Contribution 12 - * The complete RAM/ROM memory identity - * Partial degree: - */ - ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 - ap.memory_identity = - ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 - ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 - ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 - - // (deg 3 or 9) + (deg 4) + (deg 3) - ap.auxiliary_identity = ap.memory_identity + non_native_field_identity + limb_accumulator_identity; - ap.auxiliary_identity = ap.auxiliary_identity * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 10 - evals[12] = ap.auxiliary_identity; - } - - function scaleAndBatchSubrelations( - Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, - Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges - ) internal view returns (Fr accumulator) { - accumulator = accumulator + evaluations[0]; - - for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { - accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; - } - } - function verifyZeroMorph(Honk.Proof memory proof, Honk.VerificationKey memory vk, Transcript memory tp) internal view @@ -977,12 +278,12 @@ abstract contract BaseHonkVerifier is IVerifier { // f commitments are accumulated at (zm_x * r) cp.rho_pow = Fr.wrap(1); - for (uint256 i = 1; i < 34; ++i) { + for (uint256 i = 1; i <= NUMBER_UNSHIFTED; ++i) { scalars[i] = tp.zmX * cp.rho_pow; cp.rho_pow = cp.rho_pow * tp.rho; } // g commitments are accumulated at r - for (uint256 i = 34; i < 43; ++i) { + for (uint256 i = NUMBER_UNSHIFTED + 1; i <= NUMBER_OF_ENTITIES; ++i) { scalars[i] = cp.rho_pow; cp.rho_pow = cp.rho_pow * tp.rho; } @@ -999,41 +300,43 @@ abstract contract BaseHonkVerifier is IVerifier { commitments[9] = vk.qElliptic; commitments[10] = vk.qAux; commitments[11] = vk.qLookup; - commitments[12] = vk.s1; - commitments[13] = vk.s2; - commitments[14] = vk.s3; - commitments[15] = vk.s4; - commitments[16] = vk.id1; - commitments[17] = vk.id2; - commitments[18] = vk.id3; - commitments[19] = vk.id4; - commitments[20] = vk.t1; - commitments[21] = vk.t2; - commitments[22] = vk.t3; - commitments[23] = vk.t4; - commitments[24] = vk.lagrangeFirst; - commitments[25] = vk.lagrangeLast; + commitments[12] = vk.qPoseidon2External; + commitments[13] = vk.qPoseidon2Internal; + commitments[14] = vk.s1; + commitments[15] = vk.s2; + commitments[16] = vk.s3; + commitments[17] = vk.s4; + commitments[18] = vk.id1; + commitments[19] = vk.id2; + commitments[20] = vk.id3; + commitments[21] = vk.id4; + commitments[22] = vk.t1; + commitments[23] = vk.t2; + commitments[24] = vk.t3; + commitments[25] = vk.t4; + commitments[26] = vk.lagrangeFirst; + commitments[27] = vk.lagrangeLast; // Accumulate proof points - commitments[26] = convertProofPoint(proof.w1); - commitments[27] = convertProofPoint(proof.w2); - commitments[28] = convertProofPoint(proof.w3); - commitments[29] = convertProofPoint(proof.w4); - commitments[30] = convertProofPoint(proof.zPerm); - commitments[31] = convertProofPoint(proof.lookupInverses); - commitments[32] = convertProofPoint(proof.lookupReadCounts); - commitments[33] = convertProofPoint(proof.lookupReadTags); + commitments[28] = convertProofPoint(proof.w1); + commitments[29] = convertProofPoint(proof.w2); + commitments[30] = convertProofPoint(proof.w3); + commitments[31] = convertProofPoint(proof.w4); + commitments[32] = convertProofPoint(proof.zPerm); + commitments[33] = convertProofPoint(proof.lookupInverses); + commitments[34] = convertProofPoint(proof.lookupReadCounts); + commitments[35] = convertProofPoint(proof.lookupReadTags); // to be Shifted - commitments[34] = vk.t1; - commitments[35] = vk.t2; - commitments[36] = vk.t3; - commitments[37] = vk.t4; - commitments[38] = convertProofPoint(proof.w1); - commitments[39] = convertProofPoint(proof.w2); - commitments[40] = convertProofPoint(proof.w3); - commitments[41] = convertProofPoint(proof.w4); - commitments[42] = convertProofPoint(proof.zPerm); + commitments[36] = vk.t1; + commitments[37] = vk.t2; + commitments[38] = vk.t3; + commitments[39] = vk.t4; + commitments[40] = convertProofPoint(proof.w1); + commitments[41] = convertProofPoint(proof.w2); + commitments[42] = convertProofPoint(proof.w3); + commitments[43] = convertProofPoint(proof.w4); + commitments[44] = convertProofPoint(proof.zPerm); // Add scalar contributions // Add contributions: scalar * [q_k], k = 0,...,log_N, where @@ -1058,8 +361,8 @@ abstract contract BaseHonkVerifier is IVerifier { cp.x_pow_2kp1 = cp.x_pow_2kp1 * cp.x_pow_2kp1; } - scalars[43 + k] = scalar; - commitments[43 + k] = convertProofPoint(proof.zmCqs[k]); + scalars[NUMBER_OF_ENTITIES + 1 + k] = scalar; + commitments[NUMBER_OF_ENTITIES + 1 + k] = convertProofPoint(proof.zmCqs[k]); } return batchMul2(commitments, scalars); diff --git a/barretenberg/sol/src/honk/Relations.sol b/barretenberg/sol/src/honk/Relations.sol new file mode 100644 index 00000000000..685797de47f --- /dev/null +++ b/barretenberg/sol/src/honk/Relations.sol @@ -0,0 +1,710 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Aztec Labs +pragma solidity >=0.8.21; + +import { + Honk, + WIRE, + NUMBER_OF_ENTITIES, + NUMBER_OF_SUBRELATIONS, + NUMBER_OF_ALPHAS, + NUMBER_UNSHIFTED, + BATCHED_RELATION_PARTIAL_LENGTH, + CONST_PROOF_SIZE_LOG_N +} from "./HonkTypes.sol"; + +import {ecMul, ecAdd, ecSub, negateInplace, convertProofPoint} from "./utils.sol"; + +// Field arithmetic libraries +import {MINUS_ONE, MODULUS as P, Fr, FrLib} from "./Fr.sol"; +import {Transcript, TranscriptLib} from "./Transcript.sol"; + +library RelationsLib { + Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) + + function accumulateRelationEvaluations(Honk.Proof memory proof, Transcript memory tp, Fr powPartialEval) + internal + view + returns (Fr accumulator) + { + Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations = proof.sumcheckEvaluations; + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; + + // Accumulate all relations in Ultra Honk - each with varying number of subrelations + accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePermutationRelation(purportedEvaluations, tp, evaluations, powPartialEval); + accumulateLogDerivativeLookupRelation(purportedEvaluations, tp, evaluations, powPartialEval); + accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateAuxillaryRelation(purportedEvaluations, tp, evaluations, powPartialEval); + accumulatePoseidonExternalRelation(purportedEvaluations, tp, evaluations, powPartialEval); + accumulatePoseidonInternalRelation(purportedEvaluations, evaluations, powPartialEval); + // batch the subrelations with the alpha challenges to obtain the full honk relation + accumulator = scaleAndBatchSubrelations(evaluations, tp.alphas); + } + + /** + * Aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids + * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code + * editors, and thus is noisy. + */ + function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { + return p[uint256(_wire)]; + } + + /** + * Ultra Arithmetic Relation + * + */ + function accumulateArithmeticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal view { + // Relation 0 + Fr q_arith = wire(p, WIRE.Q_ARITH); + { + Fr neg_half = Fr.wrap(0) - (FrLib.invert(Fr.wrap(2))); + + Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; + accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) + + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); + accum = accum + (q_arith - Fr.wrap(1)) * wire(p, WIRE.W_4_SHIFT); + accum = accum * q_arith; + accum = accum * domainSep; + evals[0] = accum; + } + + // Relation 1 + { + Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); + accum = accum * (q_arith - Fr.wrap(2)); + accum = accum * (q_arith - Fr.wrap(1)); + accum = accum * q_arith; + accum = accum * domainSep; + evals[1] = accum; + } + } + + function accumulatePermutationRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Transcript memory tp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr grand_product_numerator; + Fr grand_product_denominator; + + { + Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * tp.beta + tp.gamma; + num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * tp.beta + tp.gamma); + num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * tp.beta + tp.gamma); + num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * tp.beta + tp.gamma); + + grand_product_numerator = num; + } + { + Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * tp.beta + tp.gamma; + den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * tp.beta + tp.gamma); + den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * tp.beta + tp.gamma); + den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * tp.beta + tp.gamma); + + grand_product_denominator = den; + } + + // Contribution 2 + { + Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; + + acc = acc + - ( + (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * tp.publicInputsDelta)) + * grand_product_denominator + ); + acc = acc * domainSep; + evals[2] = acc; + } + + // Contribution 3 + { + Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; + evals[3] = acc; + } + } + + function accumulateLogDerivativeLookupRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Transcript memory tp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr write_term; + Fr read_term; + + // Calculate the write term (the table accumulation) + { + write_term = wire(p, WIRE.TABLE_1) + tp.gamma + (wire(p, WIRE.TABLE_2) * tp.eta) + + (wire(p, WIRE.TABLE_3) * tp.etaTwo) + (wire(p, WIRE.TABLE_4) * tp.etaThree); + } + + // Calculate the write term + { + Fr derived_entry_1 = wire(p, WIRE.W_L) + tp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); + Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); + Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); + + read_term = derived_entry_1 + (derived_entry_2 * tp.eta) + (derived_entry_3 * tp.etaTwo) + + (wire(p, WIRE.Q_O) * tp.etaThree); + } + + Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; + Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; + + Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) + - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); + + // Inverse calculated correctly relation + Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; + accumulatorNone = accumulatorNone * domainSep; + + // Inverse + Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; + + evals[4] = accumulatorNone; + evals[5] = accumulatorOne; + } + + function accumulateDeltaRangeRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal view { + Fr minus_one = Fr.wrap(0) - Fr.wrap(1); + Fr minus_two = Fr.wrap(0) - Fr.wrap(2); + Fr minus_three = Fr.wrap(0) - Fr.wrap(3); + + // Compute wire differences + Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); + Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); + Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); + Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); + + // Contribution 6 + { + Fr acc = delta_1; + acc = acc * (delta_1 + minus_one); + acc = acc * (delta_1 + minus_two); + acc = acc * (delta_1 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[6] = acc; + } + + // Contribution 7 + { + Fr acc = delta_2; + acc = acc * (delta_2 + minus_one); + acc = acc * (delta_2 + minus_two); + acc = acc * (delta_2 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[7] = acc; + } + + // Contribution 8 + { + Fr acc = delta_3; + acc = acc * (delta_3 + minus_one); + acc = acc * (delta_3 + minus_two); + acc = acc * (delta_3 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[8] = acc; + } + + // Contribution 9 + { + Fr acc = delta_4; + acc = acc * (delta_4 + minus_one); + acc = acc * (delta_4 + minus_two); + acc = acc * (delta_4 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[9] = acc; + } + } + + struct EllipticParams { + // Points + Fr x_1; + Fr y_1; + Fr x_2; + Fr y_2; + Fr y_3; + Fr x_3; + // push accumulators into memory + Fr x_double_identity; + } + + function accumulateEllipticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + EllipticParams memory ep; + ep.x_1 = wire(p, WIRE.W_R); + ep.y_1 = wire(p, WIRE.W_O); + + ep.x_2 = wire(p, WIRE.W_L_SHIFT); + ep.y_2 = wire(p, WIRE.W_4_SHIFT); + ep.y_3 = wire(p, WIRE.W_O_SHIFT); + ep.x_3 = wire(p, WIRE.W_R_SHIFT); + + Fr q_sign = wire(p, WIRE.Q_L); + Fr q_is_double = wire(p, WIRE.Q_M); + + // Contribution 10 point addition, x-coordinate check + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + Fr x_diff = (ep.x_2 - ep.x_1); + Fr y1_sqr = (ep.y_1 * ep.y_1); + { + // Move to top + Fr partialEval = domainSep; + + Fr y2_sqr = (ep.y_2 * ep.y_2); + Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; + Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); + x_add_identity = x_add_identity * x_diff * x_diff; + x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; + + evals[10] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (Fr.wrap(1) - q_is_double); + } + + // Contribution 11 point addition, x-coordinate check + // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 + { + Fr y1_plus_y3 = ep.y_1 + ep.y_3; + Fr y_diff = ep.y_2 * q_sign - ep.y_1; + Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; + evals[11] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (Fr.wrap(1) - q_is_double); + } + + // Contribution 10 point doubling, x-coordinate check + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 + { + Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; + Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; + y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; + Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); + + // NOTE: pushed into memory (stack >:'( ) + ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; + + Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + evals[10] = evals[10] + acc; + } + + // Contribution 11 point doubling, y-coordinate check + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + { + Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; + Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); + evals[11] = evals[11] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + } + } + + // Constants for the auxiliary relation + Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); + Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); + + // Parameters used within the Auxiliary Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct AuxParams { + Fr limb_subproduct; + Fr non_native_field_gate_1; + Fr non_native_field_gate_2; + Fr non_native_field_gate_3; + Fr limb_accumulator_1; + Fr limb_accumulator_2; + Fr memory_record_check; + Fr partial_record_check; + Fr next_gate_access_type; + Fr record_delta; + Fr index_delta; + Fr adjacent_values_match_if_adjacent_indices_match; + Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + Fr access_check; + Fr next_gate_access_type_is_boolean; + Fr ROM_consistency_check_identity; + Fr RAM_consistency_check_identity; + Fr timestamp_delta; + Fr RAM_timestamp_check_identity; + Fr memory_identity; + Fr index_is_monotonically_increasing; + Fr auxiliary_identity; + } + + function accumulateAuxillaryRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Transcript memory tp, // sooo we take the relation parameters, if needed, from tramscript + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep // i guess this is the scaling factor? + ) internal pure { + AuxParams memory ap; + + /** + * Contribution 12 + * Non native field arithmetic gate 2 + * deg 4 + * + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * + */ + ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); + ap.non_native_field_gate_2 = + (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); + + ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; + ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); + ap.non_native_field_gate_1 = ap.limb_subproduct; + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); + + ap.non_native_field_gate_3 = ap.limb_subproduct; + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); + + Fr non_native_field_identity = + ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; + non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); + + // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm + // deg 2 + ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); + ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); + + // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm + // deg 2 + ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); + ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); + + Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; + limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 + + /** + * MEMORY + * + * A RAM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) + * * v: `value` of memory cell being accessed + * * a: `access` type of record. read: 0 = read, 1 = write + * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three + * + * A ROM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three + * + * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + + * selectors, depending on whether the gate is a RAM read/write or a ROM read + * + * | gate type | i | v2/t | v | a | r | + * | --------- | -- | ----- | -- | -- | -- | + * | ROM | w1 | w2 | w3 | -- | w4 | + * | RAM | w1 | w2 | w3 | qc | w4 | + * + * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on + * `w2` to fix its value) + * + * + */ + + /** + * Memory Record Check + * Partial degree: 1 + * Total degree: 4 + * + * A ROM/ROM access gate can be evaluated with the identity: + * + * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 + * + * For ROM gates, qc = 0 + */ + ap.memory_record_check = wire(p, WIRE.W_O) * tp.etaThree; + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * tp.etaTwo); + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * tp.eta); + ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); + ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 + ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); + + /** + * Contribution 13 & 14 + * ROM Consistency Check + * Partial degree: 1 + * Total degree: 4 + * + * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of + * records that are sorted. + * + * We apply the following checks for the sorted records: + * + * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 + * 2. index values for adjacent records are monotonically increasing + * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} + * + */ + ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); + ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); + + ap.index_is_monotonically_increasing = ap.index_delta * ap.index_delta - ap.index_delta; // deg 2 + + ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + Fr.wrap(1)) * ap.record_delta; // deg 2 + + evals[13] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 + evals[14] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 + + ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 + + /** + * Contributions 15,16,17 + * RAM Consistency Check + * + * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` + * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. + * This is validated by requiring `access` to be boolean + * + * For two adjacent entries in the sorted list if _both_ + * A) index values match + * B) adjacent access value is 0 (i.e. next gate is a READ) + * then + * C) both values must match. + * The gate boolean check is + * (A && B) => C === !(A && B) || C === !A || !B || C + * + * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized + * with a WRITE operation. + */ + Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 + ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/757): If we sorted in + // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta + // deg 1 or 4 + ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * tp.etaThree; + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * tp.etaTwo); + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * tp.eta); + ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; + + Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); + ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = ( + ap.index_delta * MINUS_ONE + Fr.wrap(1) + ) * value_delta * (ap.next_gate_access_type * MINUS_ONE + Fr.wrap(1)); // deg 3 or 6 + + // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the + // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't + // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access + // type is correct, to cover this edge case + // deg 2 or 4 + ap.next_gate_access_type_is_boolean = + ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; + + // Putting it all together... + evals[15] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation + * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 or 8 + evals[16] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 + evals[17] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 6 + + ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9 + + /** + * RAM Timestamp Consistency Check + * + * | w1 | w2 | w3 | w4 | + * | index | timestamp | timestamp_check | -- | + * + * Let delta_index = index_{i + 1} - index_{i} + * + * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i + * Else timestamp_check = 0 + */ + ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); + ap.RAM_timestamp_check_identity = + (ap.index_delta * MINUS_ONE + Fr.wrap(1)) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 + + /** + * Complete Contribution 12 + * The complete RAM/ROM memory identity + * Partial degree: + */ + ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 + ap.memory_identity = + ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 + ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 + ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 + + // (deg 3 or 9) + (deg 4) + (deg 3) + ap.auxiliary_identity = ap.memory_identity + non_native_field_identity + limb_accumulator_identity; + ap.auxiliary_identity = ap.auxiliary_identity * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 10 + evals[12] = ap.auxiliary_identity; + } + + // Big todo for poseidon params, reduce them + struct PoseidonExternalParams { + Fr s1; + Fr s2; + Fr s3; + Fr s4; + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr t0; + Fr t1; + Fr t2; + Fr t3; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonExternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Transcript memory tp, // I think this is not needed + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep // i guess this is the scaling factor? + ) internal pure { + PoseidonExternalParams memory ep; + + ep.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + ep.s2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_R); + ep.s3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_O); + ep.s4 = wire(p, WIRE.W_4) + wire(p, WIRE.Q_4); + + ep.u1 = ep.s1 * ep.s1 * ep.s1 * ep.s1 * ep.s1; + ep.u2 = ep.s2 * ep.s2 * ep.s2 * ep.s2 * ep.s2; + ep.u3 = ep.s3 * ep.s3 * ep.s3 * ep.s3 * ep.s3; + ep.u4 = ep.s4 * ep.s4 * ep.s4 * ep.s4 * ep.s4; + // matrix mul v = M_E * u with 14 additions + ep.t0 = ep.u1 + ep.u2; // u_1 + u_2 + ep.t1 = ep.u3 + ep.u4; // u_3 + u_4 + ep.t2 = ep.u2 + ep.u2 + ep.t1; // 2u_2 + // ep.t2 += ep.t1; // 2u_2 + u_3 + u_4 + ep.t3 = ep.u4 + ep.u4 + ep.t0; // 2u_4 + // ep.t3 += ep.t0; // u_1 + u_2 + 2u_4 + ep.v4 = ep.t1 + ep.t1; + ep.v4 = ep.v4 + ep.v4 + ep.t3; + // ep.v4 += ep.t3; // u_1 + u_2 + 4u_3 + 6u_4 + ep.v2 = ep.t0 + ep.t0; + ep.v2 = ep.v2 + ep.v2 + ep.t2; + // ep.v2 += ep.t2; // 4u_1 + 6u_2 + u_3 + u_4 + ep.v1 = ep.t3 + ep.v2; // 5u_1 + 7u_2 + u_3 + 3u_4 + ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4 + + ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep; + evals[18] = evals[18] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT)); + + evals[19] = evals[19] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT)); + + evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT)); + + evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + struct PoseidonInternalParams { + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr u_sum; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr s1; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonInternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + PoseidonInternalParams memory ip; + + Fr[4] memory INTERNAL_MATRIX_DIAGONAL = [ + FrLib.from(0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7), + FrLib.from(0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b), + FrLib.from(0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15), + FrLib.from(0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b) + ]; + + // add round constants + ip.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + + // apply s-box round + ip.u1 = ip.s1 * ip.s1 * ip.s1 * ip.s1 * ip.s1; + ip.u2 = wire(p, WIRE.W_R); + ip.u3 = wire(p, WIRE.W_O); + ip.u4 = wire(p, WIRE.W_4); + + // matrix mul with v = M_I * u 4 muls and 7 additions + ip.u_sum = ip.u1 + ip.u2 + ip.u3 + ip.u4; + + ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep; + + ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum; + evals[22] = evals[22] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT)); + + ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum; + evals[23] = evals[23] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT)); + + ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum; + evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT)); + + ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum; + evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + function scaleAndBatchSubrelations( + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, + Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges + ) internal pure returns (Fr accumulator) { + accumulator = accumulator + evaluations[0]; + + for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { + accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; + } + } +} diff --git a/barretenberg/sol/src/honk/Transcript.sol b/barretenberg/sol/src/honk/Transcript.sol index 2c209cf6305..1f450263a44 100644 --- a/barretenberg/sol/src/honk/Transcript.sol +++ b/barretenberg/sol/src/honk/Transcript.sol @@ -1,3 +1,5 @@ +pragma solidity >=0.8.21; + import { Honk, NUMBER_OF_ALPHAS, @@ -6,7 +8,6 @@ import { CONST_PROOF_SIZE_LOG_N } from "./HonkTypes.sol"; import {Fr, FrLib} from "./Fr.sol"; -import {LOG_N, NUMBER_OF_PUBLIC_INPUTS} from "./keys/Add2HonkVerificationKey.sol"; // Transcript library to generate fiat shamir challenges struct Transcript { @@ -16,7 +17,7 @@ struct Transcript { Fr beta; Fr gamma; Fr[NUMBER_OF_ALPHAS] alphas; - Fr[LOG_N] gateChallenges; + Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; Fr rho; // Zero morph @@ -29,66 +30,77 @@ struct Transcript { } library TranscriptLib { - function generateTranscript( - Honk.Proof memory proof, - Honk.VerificationKey memory vk, - bytes32[] calldata publicInputs - ) internal view returns (Transcript memory t) { - (t.eta, t.etaTwo, t.etaThree) = generateEtaChallenge(proof, publicInputs); + function generateTranscript(Honk.Proof memory proof, bytes32[] calldata publicInputs, uint256 publicInputsSize) + internal + view + returns (Transcript memory t) + { + Fr previousChallenge; + (t.eta, t.etaTwo, t.etaThree, previousChallenge) = generateEtaChallenge(proof, publicInputs, publicInputsSize); - (t.beta, t.gamma) = generateBetaAndGammaChallenges(t.etaThree, proof); + (t.beta, t.gamma, previousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); - t.alphas = generateAlphaChallenges(t.gamma, proof); + (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); - t.gateChallenges = generateGateChallenges(t.alphas[NUMBER_OF_ALPHAS - 1]); + (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge); - t.sumCheckUChallenges = generateSumcheckChallenges(proof, t.gateChallenges[LOG_N - 1]); - t.rho = generateRhoChallenge(proof, t.sumCheckUChallenges[CONST_PROOF_SIZE_LOG_N - 1]); + (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge); + (t.rho, previousChallenge) = generateRhoChallenge(proof, previousChallenge); - t.zmY = generateZMYChallenge(t.rho, proof); + (t.zmY, previousChallenge) = generateZMYChallenge(previousChallenge, proof); - (t.zmX, t.zmZ) = generateZMXZChallenges(t.zmY, proof); + (t.zmX, t.zmZ, previousChallenge) = generateZMXZChallenges(previousChallenge, proof); return t; } - function generateEtaChallenge(Honk.Proof memory proof, bytes32[] calldata publicInputs) + function splitChallenge(Fr challenge) internal pure returns (Fr first, Fr second) { + uint256 challengeU256 = uint256(Fr.unwrap(challenge)); + uint256 lo = challengeU256 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + uint256 hi = challengeU256 >> 128; + first = FrLib.fromBytes32(bytes32(lo)); + second = FrLib.fromBytes32(bytes32(hi)); + } + + function generateEtaChallenge(Honk.Proof memory proof, bytes32[] calldata publicInputs, uint256 publicInputsSize) internal view - returns (Fr eta, Fr etaTwo, Fr etaThree) + returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { - bytes32[3 + NUMBER_OF_PUBLIC_INPUTS + 12] memory round0; + bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12); round0[0] = bytes32(proof.circuitSize); round0[1] = bytes32(proof.publicInputsSize); round0[2] = bytes32(proof.publicInputsOffset); - for (uint256 i = 0; i < NUMBER_OF_PUBLIC_INPUTS; i++) { + for (uint256 i = 0; i < publicInputsSize; i++) { round0[3 + i] = bytes32(publicInputs[i]); } // Create the first challenge // Note: w4 is added to the challenge later on - round0[3 + NUMBER_OF_PUBLIC_INPUTS] = bytes32(proof.w1.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 1] = bytes32(proof.w1.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 2] = bytes32(proof.w1.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 3] = bytes32(proof.w1.y_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 4] = bytes32(proof.w2.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 5] = bytes32(proof.w2.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 6] = bytes32(proof.w2.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 7] = bytes32(proof.w2.y_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 8] = bytes32(proof.w3.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 9] = bytes32(proof.w3.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 10] = bytes32(proof.w3.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 11] = bytes32(proof.w3.y_1); - - eta = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); - etaTwo = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(eta)))); - etaThree = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(etaTwo)))); + round0[3 + publicInputsSize] = bytes32(proof.w1.x_0); + round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1); + round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0); + round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1); + round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0); + round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1); + round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0); + round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1); + round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0); + round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1); + round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0); + round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1); + + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); + (eta, etaTwo) = splitChallenge(previousChallenge); + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + Fr unused; + (etaThree, unused) = splitChallenge(previousChallenge); } function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.Proof memory proof) internal view - returns (Fr beta, Fr gamma) + returns (Fr beta, Fr gamma, Fr nextPreviousChallenge) { bytes32[13] memory round1; round1[0] = FrLib.toBytes32(previousChallenge); @@ -105,15 +117,15 @@ library TranscriptLib { round1[11] = bytes32(proof.w4.y_0); round1[12] = bytes32(proof.w4.y_1); - beta = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); - gamma = FrLib.fromBytes32(keccak256(abi.encodePacked(beta))); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); + (beta, gamma) = splitChallenge(nextPreviousChallenge); } // Alpha challenges non-linearise the gate contributions function generateAlphaChallenges(Fr previousChallenge, Honk.Proof memory proof) internal view - returns (Fr[NUMBER_OF_ALPHAS] memory alphas) + returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge) { // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup uint256[9] memory alpha0; @@ -127,57 +139,75 @@ library TranscriptLib { alpha0[7] = proof.zPerm.y_0; alpha0[8] = proof.zPerm.y_1; - alphas[0] = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + (alphas[0], alphas[1]) = splitChallenge(nextPreviousChallenge); - Fr prevChallenge = alphas[0]; - for (uint256 i = 1; i < NUMBER_OF_ALPHAS; i++) { - prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(prevChallenge)))); - alphas[i] = prevChallenge; + for (uint256 i = 1; i < NUMBER_OF_ALPHAS / 2; i++) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + (alphas[2 * i], alphas[2 * i + 1]) = splitChallenge(nextPreviousChallenge); + } + if (((NUMBER_OF_ALPHAS & 1) == 1) && (NUMBER_OF_ALPHAS > 2)) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + Fr unused; + (alphas[NUMBER_OF_ALPHAS - 1], unused) = splitChallenge(nextPreviousChallenge); } } - function generateGateChallenges(Fr previousChallenge) internal view returns (Fr[LOG_N] memory gateChallenges) { - for (uint256 i = 0; i < LOG_N; i++) { + function generateGateChallenges(Fr previousChallenge) + internal + view + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); - gateChallenges[i] = previousChallenge; + Fr unused; + (gateChallenges[i], unused) = splitChallenge(previousChallenge); } + nextPreviousChallenge = previousChallenge; } function generateSumcheckChallenges(Honk.Proof memory proof, Fr prevChallenge) internal view - returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges) + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges, Fr nextPreviousChallenge) { for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { Fr[BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; univariateChal[0] = prevChallenge; - // TODO(opt): memcpy + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1098): memcpy for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; } - - sumcheckChallenges[i] = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); - prevChallenge = sumcheckChallenges[i]; + prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); + Fr unused; + (sumcheckChallenges[i], unused) = splitChallenge(prevChallenge); } + nextPreviousChallenge = prevChallenge; } - function generateRhoChallenge(Honk.Proof memory proof, Fr prevChallenge) internal view returns (Fr rho) { + function generateRhoChallenge(Honk.Proof memory proof, Fr prevChallenge) + internal + view + returns (Fr rho, Fr nextPreviousChallenge) + { Fr[NUMBER_OF_ENTITIES + 1] memory rhoChallengeElements; rhoChallengeElements[0] = prevChallenge; - // TODO: memcpy + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1098): memcpy for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { rhoChallengeElements[i + 1] = proof.sumcheckEvaluations[i]; } - rho = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + Fr unused; + (rho, unused) = splitChallenge(nextPreviousChallenge); } function generateZMYChallenge(Fr previousChallenge, Honk.Proof memory proof) internal view - returns (Fr zeromorphY) + returns (Fr zeromorphY, Fr nextPreviousChallenge) { uint256[CONST_PROOF_SIZE_LOG_N * 4 + 1] memory zmY; zmY[0] = Fr.unwrap(previousChallenge); @@ -189,13 +219,15 @@ library TranscriptLib { zmY[4 + i * 4] = proof.zmCqs[i].y_1; } - zeromorphY = FrLib.fromBytes32(keccak256(abi.encodePacked(zmY))); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(zmY))); + Fr unused; + (zeromorphY, unused) = splitChallenge(nextPreviousChallenge); } function generateZMXZChallenges(Fr previousChallenge, Honk.Proof memory proof) internal - view - returns (Fr zeromorphX, Fr zeromorphZ) + pure + returns (Fr zeromorphX, Fr zeromorphZ, Fr nextPreviousChallenge) { uint256[4 + 1] memory buf; buf[0] = Fr.unwrap(previousChallenge); @@ -205,7 +237,140 @@ library TranscriptLib { buf[3] = proof.zmCq.y_0; buf[4] = proof.zmCq.y_1; - zeromorphX = FrLib.fromBytes32(keccak256(abi.encodePacked(buf))); - zeromorphZ = FrLib.fromBytes32(keccak256(abi.encodePacked(zeromorphX))); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(buf))); + (zeromorphX, zeromorphZ) = splitChallenge(nextPreviousChallenge); + } + + // TODO: mod q proof points + // TODO: Preprocess all of the memory locations + // TODO: Adjust proof point serde away from poseidon forced field elements + // TODO: move this back to probably each instance to avoid dynamic init of arrays in the Transcript Lib + function loadProof(bytes calldata proof) internal view returns (Honk.Proof memory) { + Honk.Proof memory p; + + // Metadata + p.circuitSize = uint256(bytes32(proof[0x00:0x20])); + p.publicInputsSize = uint256(bytes32(proof[0x20:0x40])); + p.publicInputsOffset = uint256(bytes32(proof[0x40:0x60])); + + // Commitments + p.w1 = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x60:0x80])), + x_1: uint256(bytes32(proof[0x80:0xa0])), + y_0: uint256(bytes32(proof[0xa0:0xc0])), + y_1: uint256(bytes32(proof[0xc0:0xe0])) + }); + + p.w2 = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0xe0:0x100])), + x_1: uint256(bytes32(proof[0x100:0x120])), + y_0: uint256(bytes32(proof[0x120:0x140])), + y_1: uint256(bytes32(proof[0x140:0x160])) + }); + p.w3 = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x160:0x180])), + x_1: uint256(bytes32(proof[0x180:0x1a0])), + y_0: uint256(bytes32(proof[0x1a0:0x1c0])), + y_1: uint256(bytes32(proof[0x1c0:0x1e0])) + }); + + // Lookup / Permutation Helper Commitments + p.lookupReadCounts = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x1e0:0x200])), + x_1: uint256(bytes32(proof[0x200:0x220])), + y_0: uint256(bytes32(proof[0x220:0x240])), + y_1: uint256(bytes32(proof[0x240:0x260])) + }); + p.lookupReadTags = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x260:0x280])), + x_1: uint256(bytes32(proof[0x280:0x2a0])), + y_0: uint256(bytes32(proof[0x2a0:0x2c0])), + y_1: uint256(bytes32(proof[0x2c0:0x2e0])) + }); + p.w4 = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x2e0:0x300])), + x_1: uint256(bytes32(proof[0x300:0x320])), + y_0: uint256(bytes32(proof[0x320:0x340])), + y_1: uint256(bytes32(proof[0x340:0x360])) + }); + p.lookupInverses = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x360:0x380])), + x_1: uint256(bytes32(proof[0x380:0x3a0])), + y_0: uint256(bytes32(proof[0x3a0:0x3c0])), + y_1: uint256(bytes32(proof[0x3c0:0x3e0])) + }); + p.zPerm = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[0x3e0:0x400])), + x_1: uint256(bytes32(proof[0x400:0x420])), + y_0: uint256(bytes32(proof[0x420:0x440])), + y_1: uint256(bytes32(proof[0x440:0x460])) + }); + + // TEMP the boundary of what has already been read + uint256 boundary = 0x460; + + // Sumcheck univariates + // TODO: in this case we know what log_n is - so we hard code it, we would want this to be included in + // a cpp template for different circuit sizes + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + // The loop boundary of i, this will shift forward on each evaluation + uint256 loop_boundary = boundary + (i * 0x20 * BATCHED_RELATION_PARTIAL_LENGTH); + + for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { + uint256 start = loop_boundary + (j * 0x20); + uint256 end = start + 0x20; + p.sumcheckUnivariates[i][j] = FrLib.fromBytes32(bytes32(proof[start:end])); + } + } + + boundary = boundary + (CONST_PROOF_SIZE_LOG_N * BATCHED_RELATION_PARTIAL_LENGTH * 0x20); + // Sumcheck evaluations + for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { + uint256 start = boundary + (i * 0x20); + uint256 end = start + 0x20; + p.sumcheckEvaluations[i] = FrLib.fromBytes32(bytes32(proof[start:end])); + } + + boundary = boundary + (NUMBER_OF_ENTITIES * 0x20); + // Zero morph Commitments + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + // Explicitly stating the x0, x1, y0, y1 start and end boundaries to make the calldata slicing bearable + uint256 xStart = boundary + (i * 0x80); + uint256 xEnd = xStart + 0x20; + + uint256 x1Start = xEnd; + uint256 x1End = x1Start + 0x20; + + uint256 yStart = x1End; + uint256 yEnd = yStart + 0x20; + + uint256 y1Start = yEnd; + uint256 y1End = y1Start + 0x20; + + p.zmCqs[i] = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[xStart:xEnd])), + x_1: uint256(bytes32(proof[x1Start:x1End])), + y_0: uint256(bytes32(proof[yStart:yEnd])), + y_1: uint256(bytes32(proof[y1Start:y1End])) + }); + } + + boundary = boundary + (CONST_PROOF_SIZE_LOG_N * 0x80); + + p.zmCq = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[boundary:boundary + 0x20])), + x_1: uint256(bytes32(proof[boundary + 0x20:boundary + 0x40])), + y_0: uint256(bytes32(proof[boundary + 0x40:boundary + 0x60])), + y_1: uint256(bytes32(proof[boundary + 0x60:boundary + 0x80])) + }); + + p.zmPi = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proof[boundary + 0x80:boundary + 0xa0])), + x_1: uint256(bytes32(proof[boundary + 0xa0:boundary + 0xc0])), + y_0: uint256(bytes32(proof[boundary + 0xc0:boundary + 0xe0])), + y_1: uint256(bytes32(proof[boundary + 0xe0:boundary + 0x100])) + }); + + return p; } } diff --git a/barretenberg/sol/src/honk/instance/Add2Honk.sol b/barretenberg/sol/src/honk/instance/Add2Honk.sol index 06be6aa1a25..9f554d10b54 100644 --- a/barretenberg/sol/src/honk/instance/Add2Honk.sol +++ b/barretenberg/sol/src/honk/instance/Add2Honk.sol @@ -1,7 +1,4 @@ // SPDX-License-Identifier: Apache-2.0 - -// NOTE: to work around solidity not allowing templates, we need a transcript class and proof class for each - // Copyright 2024 Aztec Labs pragma solidity >=0.8.21; @@ -14,222 +11,19 @@ import { NUMBER_OF_ENTITIES, NUMBER_OF_SUBRELATIONS, NUMBER_OF_ALPHAS, + NUMBER_UNSHIFTED, BATCHED_RELATION_PARTIAL_LENGTH, - CONST_PROOF_SIZE_LOG_N, - P, - Q + CONST_PROOF_SIZE_LOG_N } from "../HonkTypes.sol"; import {ecMul, ecAdd, ecSub, negateInplace, convertProofPoint} from "../utils.sol"; -// Field arithmetic libraries -import {Fr, FrLib} from "../Fr.sol"; - -// Transcript library to generate fiat shamir challenges -struct Transcript { - Fr eta; - Fr etaTwo; - Fr etaThree; - Fr beta; - Fr gamma; - Fr[NUMBER_OF_ALPHAS] alphas; - Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; - Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; - Fr rho; - // Zero morph - Fr zmX; - Fr zmY; - Fr zmZ; - Fr zmQuotient; - // Derived - Fr publicInputsDelta; -} - -library TranscriptLib { - function generateTranscript( - Honk.Proof memory proof, - Honk.VerificationKey memory vk, - bytes32[] calldata publicInputs - ) internal view returns (Transcript memory t) { - (t.eta, t.etaTwo, t.etaThree) = generateEtaChallenge(proof, publicInputs); - - (t.beta, t.gamma) = generateBetaAndGammaChallenges(t.etaThree, proof); - - t.alphas = generateAlphaChallenges(t.gamma, proof); - - t.gateChallenges = generateGateChallenges(t.alphas[NUMBER_OF_ALPHAS - 1]); - - t.sumCheckUChallenges = generateSumcheckChallenges(proof, t.gateChallenges[CONST_PROOF_SIZE_LOG_N - 1]); - t.rho = generateRhoChallenge(proof, t.sumCheckUChallenges[CONST_PROOF_SIZE_LOG_N - 1]); - - t.zmY = generateZMYChallenge(t.rho, proof); - - (t.zmX, t.zmZ) = generateZMXZChallenges(t.zmY, proof); - - return t; - } - - function generateEtaChallenge(Honk.Proof memory proof, bytes32[] calldata publicInputs) - internal - view - returns (Fr eta, Fr etaTwo, Fr etaThree) - { - bytes32[3 + NUMBER_OF_PUBLIC_INPUTS + 12] memory round0; - round0[0] = bytes32(proof.circuitSize); - round0[1] = bytes32(proof.publicInputsSize); - round0[2] = bytes32(proof.publicInputsOffset); - for (uint256 i = 0; i < NUMBER_OF_PUBLIC_INPUTS; i++) { - round0[3 + i] = bytes32(publicInputs[i]); - } - - // Create the first challenge - // Note: w4 is added to the challenge later on - round0[3 + NUMBER_OF_PUBLIC_INPUTS] = bytes32(proof.w1.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 1] = bytes32(proof.w1.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 2] = bytes32(proof.w1.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 3] = bytes32(proof.w1.y_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 4] = bytes32(proof.w2.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 5] = bytes32(proof.w2.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 6] = bytes32(proof.w2.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 7] = bytes32(proof.w2.y_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 8] = bytes32(proof.w3.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 9] = bytes32(proof.w3.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 10] = bytes32(proof.w3.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 11] = bytes32(proof.w3.y_1); - - eta = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); - etaTwo = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(eta)))); - etaThree = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(etaTwo)))); - } - - function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr beta, Fr gamma) - { - bytes32[13] memory round1; - round1[0] = FrLib.toBytes32(previousChallenge); - round1[1] = bytes32(proof.lookupReadCounts.x_0); - round1[2] = bytes32(proof.lookupReadCounts.x_1); - round1[3] = bytes32(proof.lookupReadCounts.y_0); - round1[4] = bytes32(proof.lookupReadCounts.y_1); - round1[5] = bytes32(proof.lookupReadTags.x_0); - round1[6] = bytes32(proof.lookupReadTags.x_1); - round1[7] = bytes32(proof.lookupReadTags.y_0); - round1[8] = bytes32(proof.lookupReadTags.y_1); - round1[9] = bytes32(proof.w4.x_0); - round1[10] = bytes32(proof.w4.x_1); - round1[11] = bytes32(proof.w4.y_0); - round1[12] = bytes32(proof.w4.y_1); - - beta = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); - gamma = FrLib.fromBytes32(keccak256(abi.encodePacked(beta))); - } - - // Alpha challenges non-linearise the gate contributions - function generateAlphaChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr[NUMBER_OF_ALPHAS] memory alphas) - { - // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup - uint256[9] memory alpha0; - alpha0[0] = Fr.unwrap(previousChallenge); - alpha0[1] = proof.lookupInverses.x_0; - alpha0[2] = proof.lookupInverses.x_1; - alpha0[3] = proof.lookupInverses.y_0; - alpha0[4] = proof.lookupInverses.y_1; - alpha0[5] = proof.zPerm.x_0; - alpha0[6] = proof.zPerm.x_1; - alpha0[7] = proof.zPerm.y_0; - alpha0[8] = proof.zPerm.y_1; - - alphas[0] = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); - - Fr prevChallenge = alphas[0]; - for (uint256 i = 1; i < NUMBER_OF_ALPHAS; i++) { - prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(prevChallenge)))); - alphas[i] = prevChallenge; - } - } - - function generateGateChallenges(Fr previousChallenge) - internal - view - returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges) - { - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); - gateChallenges[i] = previousChallenge; - } - } - - function generateSumcheckChallenges(Honk.Proof memory proof, Fr prevChallenge) - internal - view - returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges) - { - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - Fr[BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; - univariateChal[0] = prevChallenge; - - // TODO(opt): memcpy - for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { - univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; - } - - sumcheckChallenges[i] = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); - prevChallenge = sumcheckChallenges[i]; - } - } - - function generateRhoChallenge(Honk.Proof memory proof, Fr prevChallenge) internal view returns (Fr rho) { - Fr[NUMBER_OF_ENTITIES + 1] memory rhoChallengeElements; - rhoChallengeElements[0] = prevChallenge; - - // TODO: memcpy - for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { - rhoChallengeElements[i + 1] = proof.sumcheckEvaluations[i]; - } - - rho = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); - } - - function generateZMYChallenge(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr zeromorphY) - { - uint256[CONST_PROOF_SIZE_LOG_N * 4 + 1] memory zmY; - zmY[0] = Fr.unwrap(previousChallenge); - - for (uint256 i; i < CONST_PROOF_SIZE_LOG_N; ++i) { - zmY[1 + i * 4] = proof.zmCqs[i].x_0; - zmY[2 + i * 4] = proof.zmCqs[i].x_1; - zmY[3 + i * 4] = proof.zmCqs[i].y_0; - zmY[4 + i * 4] = proof.zmCqs[i].y_1; - } +// Field arithmetic libraries - prevent littering the code with modmul / addmul +import {MODULUS as P, MINUS_ONE, Fr, FrLib} from "../Fr.sol"; - zeromorphY = FrLib.fromBytes32(keccak256(abi.encodePacked(zmY))); - } +import {Transcript, TranscriptLib} from "../Transcript.sol"; - function generateZMXZChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr zeromorphX, Fr zeromorphZ) - { - uint256[4 + 1] memory buf; - buf[0] = Fr.unwrap(previousChallenge); - - buf[1] = proof.zmCq.x_0; - buf[2] = proof.zmCq.x_1; - buf[3] = proof.zmCq.y_0; - buf[4] = proof.zmCq.y_1; - - zeromorphX = FrLib.fromBytes32(keccak256(abi.encodePacked(buf))); - zeromorphZ = FrLib.fromBytes32(keccak256(abi.encodePacked(zeromorphX))); - } -} +import {RelationsLib} from "../Relations.sol"; // Errors error PublicInputsLengthWrong(); @@ -238,18 +32,16 @@ error ZeromorphFailed(); /// Smart contract verifier of honk proofs contract Add2HonkVerifier is IVerifier { - Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) - function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) { Honk.VerificationKey memory vk = loadVerificationKey(); - Honk.Proof memory p = loadProof(proof); + Honk.Proof memory p = TranscriptLib.loadProof(proof); if (publicInputs.length != vk.publicInputsSize) { revert PublicInputsLengthWrong(); } // Generate the fiat shamir challenges for the whole protocol - Transcript memory t = TranscriptLib.generateTranscript(p, vk, publicInputs); + Transcript memory t = TranscriptLib.generateTranscript(p, publicInputs, vk.publicInputsSize); // Compute the public input delta t.publicInputsDelta = @@ -270,139 +62,6 @@ contract Add2HonkVerifier is IVerifier { return VK.loadVerificationKey(); } - // TODO: mod q proof points - // TODO: Preprocess all of the memory locations - // TODO: Adjust proof point serde away from poseidon forced field elements - function loadProof(bytes calldata proof) internal view returns (Honk.Proof memory) { - Honk.Proof memory p; - - // Metadata - p.circuitSize = uint256(bytes32(proof[0x00:0x20])); - p.publicInputsSize = uint256(bytes32(proof[0x20:0x40])); - p.publicInputsOffset = uint256(bytes32(proof[0x40:0x60])); - - // Commitments - p.w1 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x60:0x80])), - x_1: uint256(bytes32(proof[0x80:0xa0])), - y_0: uint256(bytes32(proof[0xa0:0xc0])), - y_1: uint256(bytes32(proof[0xc0:0xe0])) - }); - - p.w2 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0xe0:0x100])), - x_1: uint256(bytes32(proof[0x100:0x120])), - y_0: uint256(bytes32(proof[0x120:0x140])), - y_1: uint256(bytes32(proof[0x140:0x160])) - }); - p.w3 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x160:0x180])), - x_1: uint256(bytes32(proof[0x180:0x1a0])), - y_0: uint256(bytes32(proof[0x1a0:0x1c0])), - y_1: uint256(bytes32(proof[0x1c0:0x1e0])) - }); - - // Lookup / Permutation Helper Commitments - // TODO(md): update the log deriv prover commitment rounds - p.lookupReadCounts = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x1e0:0x200])), - x_1: uint256(bytes32(proof[0x200:0x220])), - y_0: uint256(bytes32(proof[0x220:0x240])), - y_1: uint256(bytes32(proof[0x240:0x260])) - }); - p.lookupReadTags = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x260:0x280])), - x_1: uint256(bytes32(proof[0x280:0x2a0])), - y_0: uint256(bytes32(proof[0x2a0:0x2c0])), - y_1: uint256(bytes32(proof[0x2c0:0x2e0])) - }); - p.w4 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x2e0:0x300])), - x_1: uint256(bytes32(proof[0x300:0x320])), - y_0: uint256(bytes32(proof[0x320:0x340])), - y_1: uint256(bytes32(proof[0x340:0x360])) - }); - p.lookupInverses = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x360:0x380])), - x_1: uint256(bytes32(proof[0x380:0x3a0])), - y_0: uint256(bytes32(proof[0x3a0:0x3c0])), - y_1: uint256(bytes32(proof[0x3c0:0x3e0])) - }); - p.zPerm = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x3e0:0x400])), - x_1: uint256(bytes32(proof[0x400:0x420])), - y_0: uint256(bytes32(proof[0x420:0x440])), - y_1: uint256(bytes32(proof[0x440:0x460])) - }); - - // TEMP the boundary of what has already been read - uint256 boundary = 0x460; - - // Sumcheck univariates - // TODO: in this case we know what log_n is - so we hard code it, we would want this to be included in - // a cpp template for different circuit sizes - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - // The loop boundary of i, this will shift forward on each evaluation - uint256 loop_boundary = boundary + (i * 0x20 * BATCHED_RELATION_PARTIAL_LENGTH); - - for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { - uint256 start = loop_boundary + (j * 0x20); - uint256 end = start + 0x20; - p.sumcheckUnivariates[i][j] = FrLib.fromBytes32(bytes32(proof[start:end])); - } - } - - boundary = boundary + (CONST_PROOF_SIZE_LOG_N * BATCHED_RELATION_PARTIAL_LENGTH * 0x20); - // Sumcheck evaluations - for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { - uint256 start = boundary + (i * 0x20); - uint256 end = start + 0x20; - p.sumcheckEvaluations[i] = FrLib.fromBytes32(bytes32(proof[start:end])); - } - - boundary = boundary + (NUMBER_OF_ENTITIES * 0x20); - // Zero morph Commitments - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - // Explicitly stating the x0, x1, y0, y1 start and end boundaries to make the calldata slicing bearable - uint256 xStart = boundary + (i * 0x80); - uint256 xEnd = xStart + 0x20; - - uint256 x1Start = xEnd; - uint256 x1End = x1Start + 0x20; - - uint256 yStart = x1End; - uint256 yEnd = yStart + 0x20; - - uint256 y1Start = yEnd; - uint256 y1End = y1Start + 0x20; - - p.zmCqs[i] = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[xStart:xEnd])), - x_1: uint256(bytes32(proof[x1Start:x1End])), - y_0: uint256(bytes32(proof[yStart:yEnd])), - y_1: uint256(bytes32(proof[y1Start:y1End])) - }); - } - - boundary = boundary + (CONST_PROOF_SIZE_LOG_N * 0x80); - - p.zmCq = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[boundary:boundary + 0x20])), - x_1: uint256(bytes32(proof[boundary + 0x20:boundary + 0x40])), - y_0: uint256(bytes32(proof[boundary + 0x40:boundary + 0x60])), - y_1: uint256(bytes32(proof[boundary + 0x60:boundary + 0x80])) - }); - - p.zmPi = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[boundary + 0x80:boundary + 0xa0])), - x_1: uint256(bytes32(proof[boundary + 0xa0:boundary + 0xc0])), - y_0: uint256(bytes32(proof[boundary + 0xc0:boundary + 0xe0])), - y_1: uint256(bytes32(proof[boundary + 0xe0:boundary + 0x100])) - }); - - return p; - } - function computePublicInputDelta( bytes32[] memory publicInputs, Fr beta, @@ -452,7 +111,7 @@ contract Add2HonkVerifier is IVerifier { } // Last round - Fr grandHonkRelationSum = accumulateRelationEvaluations(proof, tp, powPartialEvaluation); + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations(proof, tp, powPartialEvaluation); verified = (grandHonkRelationSum == roundTarget); } @@ -472,18 +131,27 @@ contract Add2HonkVerifier is IVerifier { returns (Fr targetSum) { // TODO: inline - Fr[7] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000002d0), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff89), - Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000030), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffdd), - Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000030), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff89), - Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000002d0) + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff11), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000090), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff71), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000000f0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000013b0) ]; - Fr[7] memory BARYCENTRIC_DOMAIN = - [Fr.wrap(0x00), Fr.wrap(0x01), Fr.wrap(0x02), Fr.wrap(0x03), Fr.wrap(0x04), Fr.wrap(0x05), Fr.wrap(0x06)]; + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_DOMAIN = [ + Fr.wrap(0x00), + Fr.wrap(0x01), + Fr.wrap(0x02), + Fr.wrap(0x03), + Fr.wrap(0x04), + Fr.wrap(0x05), + Fr.wrap(0x06), + Fr.wrap(0x07) + ]; // To compute the next target sum, we evaluate the given univariate at a point u (challenge). // TODO: opt: use same array mem for each iteratioon @@ -516,590 +184,13 @@ contract Add2HonkVerifier is IVerifier { // Univariate evaluation of the monomial ((1-X_l) + X_l.B_l) at the challenge point X_l=u_l function partiallyEvaluatePOW(Transcript memory tp, Fr currentEvaluation, Fr roundChallenge, uint256 round) internal - view + pure returns (Fr newEvaluation) { Fr univariateEval = Fr.wrap(1) + (roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); newEvaluation = currentEvaluation * univariateEval; } - // Calculate the contributions of each relation to the expected value of the full honk relation - // - // For each relation, we use the purported values ( the ones provided by the prover ) of the multivariates to - // calculate a contribution to the purported value of the full Honk relation. - // These are stored in the evaluations part of the proof object. - // We add these together, with the appropiate scaling factor ( the alphas calculated in challenges ) - // This value is checked against the final value of the target total sum - et voila! - function accumulateRelationEvaluations(Honk.Proof memory proof, Transcript memory tp, Fr powPartialEval) - internal - view - returns (Fr accumulator) - { - Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations = proof.sumcheckEvaluations; - Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; - - // Accumulate all 6 custom gates - each with varying number of subrelations - accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); - accumulatePermutationRelation(purportedEvaluations, tp, evaluations, powPartialEval); - accumulateLogDerivativeLookupRelation(purportedEvaluations, tp, evaluations, powPartialEval); - accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); - accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); - accumulateAuxillaryRelation(purportedEvaluations, tp, evaluations, powPartialEval); - - // Apply alpha challenges to challenge evaluations - // Returns grand honk realtion evaluation - accumulator = scaleAndBatchSubrelations(evaluations, tp.alphas); - } - - /** - * WIRE - * - * Wire is an aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids - * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code - * editors, and thus is noisy. - */ - function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { - return p[uint256(_wire)]; - } - - /** - * Ultra Arithmetic Relation - * - */ - function accumulateArithmeticRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - // Relation 0 - Fr q_arith = wire(p, WIRE.Q_ARITH); - { - Fr neg_half = Fr.wrap(0) - (FrLib.invert(Fr.wrap(2))); - - Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; - accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) - + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); - accum = accum + (q_arith - Fr.wrap(1)) * wire(p, WIRE.W_4_SHIFT); - accum = accum * q_arith; - accum = accum * domainSep; - evals[0] = accum; - } - - // Relation 1 - { - Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); - accum = accum * (q_arith - Fr.wrap(2)); - accum = accum * (q_arith - Fr.wrap(1)); - accum = accum * q_arith; - accum = accum * domainSep; - evals[1] = accum; - } - } - - function accumulatePermutationRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr grand_product_numerator; - Fr grand_product_denominator; - - { - Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * tp.beta + tp.gamma; - num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * tp.beta + tp.gamma); - num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * tp.beta + tp.gamma); - num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * tp.beta + tp.gamma); - - grand_product_numerator = num; - } - { - Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * tp.beta + tp.gamma; - den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * tp.beta + tp.gamma); - den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * tp.beta + tp.gamma); - den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * tp.beta + tp.gamma); - - grand_product_denominator = den; - } - - // Contribution 2 - { - Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; - - acc = acc - - ( - (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * tp.publicInputsDelta)) - * grand_product_denominator - ); - acc = acc * domainSep; - evals[2] = acc; - } - - // Contribution 3 - { - Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; - evals[3] = acc; - } - } - - function accumulateLogDerivativeLookupRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr write_term; - Fr read_term; - - // Calculate the write term (the table accumulation) - { - write_term = wire(p, WIRE.TABLE_1) + tp.gamma + (wire(p, WIRE.TABLE_2) * tp.eta) - + (wire(p, WIRE.TABLE_3) * tp.etaTwo) + (wire(p, WIRE.TABLE_4) * tp.etaThree); - } - - // Calculate the write term - { - Fr derived_entry_1 = wire(p, WIRE.W_L) + tp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); - Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); - Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); - - read_term = derived_entry_1 + (derived_entry_2 * tp.eta) + (derived_entry_3 * tp.etaTwo) - + (wire(p, WIRE.Q_O) * tp.etaThree); - } - - Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; - Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; - - Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) - - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); - - // Inverse calculated correctly relation - Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; - accumulatorNone = accumulatorNone * domainSep; - - // Inverse - Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; - - evals[4] = accumulatorNone; - evals[5] = accumulatorOne; - } - - function accumulateDeltaRangeRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr minus_one = Fr.wrap(0) - Fr.wrap(1); - Fr minus_two = Fr.wrap(0) - Fr.wrap(2); - Fr minus_three = Fr.wrap(0) - Fr.wrap(3); - - // Compute wire differences - Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); - Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); - Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); - Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); - - // Contribution 6 - { - Fr acc = delta_1; - acc = acc * (delta_1 + minus_one); - acc = acc * (delta_1 + minus_two); - acc = acc * (delta_1 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[6] = acc; - } - - // Contribution 7 - { - Fr acc = delta_2; - acc = acc * (delta_2 + minus_one); - acc = acc * (delta_2 + minus_two); - acc = acc * (delta_2 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[7] = acc; - } - - // Contribution 8 - { - Fr acc = delta_3; - acc = acc * (delta_3 + minus_one); - acc = acc * (delta_3 + minus_two); - acc = acc * (delta_3 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[8] = acc; - } - - // Contribution 9 - { - Fr acc = delta_4; - acc = acc * (delta_4 + minus_one); - acc = acc * (delta_4 + minus_two); - acc = acc * (delta_4 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[9] = acc; - } - } - - struct EllipticParams { - // Points - Fr x_1; - Fr y_1; - Fr x_2; - Fr y_2; - Fr y_3; - Fr x_3; - // push accumulators into memory - Fr x_double_identity; - } - - function accumulateEllipticRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - EllipticParams memory ep; - ep.x_1 = wire(p, WIRE.W_R); - ep.y_1 = wire(p, WIRE.W_O); - - ep.x_2 = wire(p, WIRE.W_L_SHIFT); - ep.y_2 = wire(p, WIRE.W_4_SHIFT); - ep.y_3 = wire(p, WIRE.W_O_SHIFT); - ep.x_3 = wire(p, WIRE.W_R_SHIFT); - - Fr q_sign = wire(p, WIRE.Q_L); - Fr q_is_double = wire(p, WIRE.Q_M); - - // Contribution 10 point addition, x-coordinate check - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - Fr x_diff = (ep.x_2 - ep.x_1); - Fr y1_sqr = (ep.y_1 * ep.y_1); - { - // Move to top - Fr partialEval = domainSep; - - Fr y2_sqr = (ep.y_2 * ep.y_2); - Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; - Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); - x_add_identity = x_add_identity * x_diff * x_diff; - x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; - - evals[10] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (Fr.wrap(1) - q_is_double); - } - - // Contribution 11 point addition, x-coordinate check - // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 - { - Fr y1_plus_y3 = ep.y_1 + ep.y_3; - Fr y_diff = ep.y_2 * q_sign - ep.y_1; - Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; - evals[11] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (Fr.wrap(1) - q_is_double); - } - - // Contribution 10 point doubling, x-coordinate check - // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 - // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 - { - Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; - Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; - y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; - Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); - - // NOTE: pushed into memory (stack >:'( ) - ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; - - Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; - evals[10] = evals[10] + acc; - } - - // Contribution 11 point doubling, y-coordinate check - // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 - { - Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; - Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); - evals[11] = evals[11] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; - } - } - - // Constants for the auxiliary relation - Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); - Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); - Fr constant MINUS_ONE = Fr.wrap(P - 1); - - // Parameters used within the Auxiliary Relation - // A struct is used to work around stack too deep. This relation has alot of variables - struct AuxParams { - Fr limb_subproduct; - Fr non_native_field_gate_1; - Fr non_native_field_gate_2; - Fr non_native_field_gate_3; - Fr limb_accumulator_1; - Fr limb_accumulator_2; - Fr memory_record_check; - Fr partial_record_check; - Fr next_gate_access_type; - Fr record_delta; - Fr index_delta; - Fr adjacent_values_match_if_adjacent_indices_match; - Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; - Fr access_check; - Fr next_gate_access_type_is_boolean; - Fr ROM_consistency_check_identity; - Fr RAM_consistency_check_identity; - Fr timestamp_delta; - Fr RAM_timestamp_check_identity; - Fr memory_identity; - Fr index_is_monotonically_increasing; - Fr auxiliary_identity; - } - - function accumulateAuxillaryRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal pure { - AuxParams memory ap; - - /** - * Contribution 12 - * Non native field arithmetic gate 2 - * deg 4 - * - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - * - */ - ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); - ap.non_native_field_gate_2 = - (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); - - ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; - ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); - ap.non_native_field_gate_1 = ap.limb_subproduct; - ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); - ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); - - ap.non_native_field_gate_3 = ap.limb_subproduct; - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); - - Fr non_native_field_identity = - ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; - non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); - - // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm - // deg 2 - ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); - ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); - - // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm - // deg 2 - ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); - ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); - - Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; - limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 - - /** - * MEMORY - * - * A RAM memory record contains a tuple of the following fields: - * * i: `index` of memory cell being accessed - * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) - * * v: `value` of memory cell being accessed - * * a: `access` type of record. read: 0 = read, 1 = write - * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three - * - * A ROM memory record contains a tuple of the following fields: - * * i: `index` of memory cell being accessed - * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) - * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) - * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three - * - * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + - * selectors, depending on whether the gate is a RAM read/write or a ROM read - * - * | gate type | i | v2/t | v | a | r | - * | --------- | -- | ----- | -- | -- | -- | - * | ROM | w1 | w2 | w3 | -- | w4 | - * | RAM | w1 | w2 | w3 | qc | w4 | - * - * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on - * `w2` to fix its value) - * - * - */ - - /** - * Memory Record Check - * Partial degree: 1 - * Total degree: 4 - * - * A ROM/ROM access gate can be evaluated with the identity: - * - * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 - * - * For ROM gates, qc = 0 - */ - ap.memory_record_check = wire(p, WIRE.W_O) * tp.etaThree; - ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * tp.etaTwo); - ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * tp.eta); - ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); - ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 - ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); - - /** - * Contribution 13 & 14 - * ROM Consistency Check - * Partial degree: 1 - * Total degree: 4 - * - * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of - * records that are sorted. - * - * We apply the following checks for the sorted records: - * - * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 - * 2. index values for adjacent records are monotonically increasing - * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} - * - */ - ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); - ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); - - ap.index_is_monotonically_increasing = ap.index_delta * ap.index_delta - ap.index_delta; // deg 2 - - ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + Fr.wrap(1)) * ap.record_delta; // deg 2 - - evals[13] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) - * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 - evals[14] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) - * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 - - ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 - - /** - * Contributions 15,16,17 - * RAM Consistency Check - * - * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` - * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. - * This is validated by requiring `access` to be boolean - * - * For two adjacent entries in the sorted list if _both_ - * A) index values match - * B) adjacent access value is 0 (i.e. next gate is a READ) - * then - * C) both values must match. - * The gate boolean check is - * (A && B) => C === !(A && B) || C === !A || !B || C - * - * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized - * with a WRITE operation. - */ - Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 - ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 - - // TODO(https://github.com/AztecProtocol/barretenberg/issues/757): If we sorted in - // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta - // deg 1 or 4 - ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * tp.etaThree; - ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * tp.etaTwo); - ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * tp.eta); - ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; - - Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); - ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = ( - ap.index_delta * MINUS_ONE + Fr.wrap(1) - ) * value_delta * (ap.next_gate_access_type * MINUS_ONE + Fr.wrap(1)); // deg 3 or 6 - - // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the - // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't - // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access - // type is correct, to cover this edge case - // deg 2 or 4 - ap.next_gate_access_type_is_boolean = - ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; - - // Putting it all together... - evals[15] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation - * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 or 8 - evals[16] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 - evals[17] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 6 - - ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9 - - /** - * RAM Timestamp Consistency Check - * - * | w1 | w2 | w3 | w4 | - * | index | timestamp | timestamp_check | -- | - * - * Let delta_index = index_{i + 1} - index_{i} - * - * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i - * Else timestamp_check = 0 - */ - ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); - ap.RAM_timestamp_check_identity = - (ap.index_delta * MINUS_ONE + Fr.wrap(1)) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 - - /** - * Complete Contribution 12 - * The complete RAM/ROM memory identity - * Partial degree: - */ - ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 - ap.memory_identity = - ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 - ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 - ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 - - // (deg 3 or 9) + (deg 4) + (deg 3) - ap.auxiliary_identity = ap.memory_identity + non_native_field_identity + limb_accumulator_identity; - ap.auxiliary_identity = ap.auxiliary_identity * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 10 - evals[12] = ap.auxiliary_identity; - } - - function scaleAndBatchSubrelations( - Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, - Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges - ) internal view returns (Fr accumulator) { - accumulator = accumulator + evaluations[0]; - - for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { - accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; - } - } - function verifyZeroMorph(Honk.Proof memory proof, Honk.VerificationKey memory vk, Transcript memory tp) internal view @@ -1185,12 +276,12 @@ contract Add2HonkVerifier is IVerifier { // f commitments are accumulated at (zm_x * r) cp.rho_pow = Fr.wrap(1); - for (uint256 i = 1; i < 34; ++i) { + for (uint256 i = 1; i <= NUMBER_UNSHIFTED; ++i) { scalars[i] = tp.zmX * cp.rho_pow; cp.rho_pow = cp.rho_pow * tp.rho; } // g commitments are accumulated at r - for (uint256 i = 34; i < 43; ++i) { + for (uint256 i = NUMBER_UNSHIFTED + 1; i <= NUMBER_OF_ENTITIES; ++i) { scalars[i] = cp.rho_pow; cp.rho_pow = cp.rho_pow * tp.rho; } @@ -1207,41 +298,43 @@ contract Add2HonkVerifier is IVerifier { commitments[9] = vk.qElliptic; commitments[10] = vk.qAux; commitments[11] = vk.qLookup; - commitments[12] = vk.s1; - commitments[13] = vk.s2; - commitments[14] = vk.s3; - commitments[15] = vk.s4; - commitments[16] = vk.id1; - commitments[17] = vk.id2; - commitments[18] = vk.id3; - commitments[19] = vk.id4; - commitments[20] = vk.t1; - commitments[21] = vk.t2; - commitments[22] = vk.t3; - commitments[23] = vk.t4; - commitments[24] = vk.lagrangeFirst; - commitments[25] = vk.lagrangeLast; + commitments[12] = vk.qPoseidon2External; + commitments[13] = vk.qPoseidon2Internal; + commitments[14] = vk.s1; + commitments[15] = vk.s2; + commitments[16] = vk.s3; + commitments[17] = vk.s4; + commitments[18] = vk.id1; + commitments[19] = vk.id2; + commitments[20] = vk.id3; + commitments[21] = vk.id4; + commitments[22] = vk.t1; + commitments[23] = vk.t2; + commitments[24] = vk.t3; + commitments[25] = vk.t4; + commitments[26] = vk.lagrangeFirst; + commitments[27] = vk.lagrangeLast; // Accumulate proof points - commitments[26] = convertProofPoint(proof.w1); - commitments[27] = convertProofPoint(proof.w2); - commitments[28] = convertProofPoint(proof.w3); - commitments[29] = convertProofPoint(proof.w4); - commitments[30] = convertProofPoint(proof.zPerm); - commitments[31] = convertProofPoint(proof.lookupInverses); - commitments[32] = convertProofPoint(proof.lookupReadCounts); - commitments[33] = convertProofPoint(proof.lookupReadTags); + commitments[28] = convertProofPoint(proof.w1); + commitments[29] = convertProofPoint(proof.w2); + commitments[30] = convertProofPoint(proof.w3); + commitments[31] = convertProofPoint(proof.w4); + commitments[32] = convertProofPoint(proof.zPerm); + commitments[33] = convertProofPoint(proof.lookupInverses); + commitments[34] = convertProofPoint(proof.lookupReadCounts); + commitments[35] = convertProofPoint(proof.lookupReadTags); // to be Shifted - commitments[34] = vk.t1; - commitments[35] = vk.t2; - commitments[36] = vk.t3; - commitments[37] = vk.t4; - commitments[38] = convertProofPoint(proof.w1); - commitments[39] = convertProofPoint(proof.w2); - commitments[40] = convertProofPoint(proof.w3); - commitments[41] = convertProofPoint(proof.w4); - commitments[42] = convertProofPoint(proof.zPerm); + commitments[36] = vk.t1; + commitments[37] = vk.t2; + commitments[38] = vk.t3; + commitments[39] = vk.t4; + commitments[40] = convertProofPoint(proof.w1); + commitments[41] = convertProofPoint(proof.w2); + commitments[42] = convertProofPoint(proof.w3); + commitments[43] = convertProofPoint(proof.w4); + commitments[44] = convertProofPoint(proof.zPerm); // Add scalar contributions // Add contributions: scalar * [q_k], k = 0,...,log_N, where @@ -1266,8 +359,8 @@ contract Add2HonkVerifier is IVerifier { cp.x_pow_2kp1 = cp.x_pow_2kp1 * cp.x_pow_2kp1; } - scalars[43 + k] = scalar; - commitments[43 + k] = convertProofPoint(proof.zmCqs[k]); + scalars[NUMBER_OF_ENTITIES + 1 + k] = scalar; + commitments[NUMBER_OF_ENTITIES + 1 + k] = convertProofPoint(proof.zmCqs[k]); } return batchMul2(commitments, scalars); @@ -1286,7 +379,7 @@ contract Add2HonkVerifier is IVerifier { let free := mload(0x40) // Write the original into the accumulator - // Load into memory for ecMUL, leave offset for eccAdd result + // Load into memory forecMUL, leave offset foreccAdd result // base is an array of pointers, so we have to dereference them mstore(add(free, 0x40), mload(mload(base))) mstore(add(free, 0x60), mload(add(0x20, mload(base)))) diff --git a/barretenberg/sol/src/honk/instance/BlakeHonk.sol b/barretenberg/sol/src/honk/instance/BlakeHonk.sol index 3bc154de40b..f3b36f359b2 100644 --- a/barretenberg/sol/src/honk/instance/BlakeHonk.sol +++ b/barretenberg/sol/src/honk/instance/BlakeHonk.sol @@ -11,222 +11,19 @@ import { NUMBER_OF_ENTITIES, NUMBER_OF_SUBRELATIONS, NUMBER_OF_ALPHAS, + NUMBER_UNSHIFTED, BATCHED_RELATION_PARTIAL_LENGTH, - CONST_PROOF_SIZE_LOG_N, - P, - Q + CONST_PROOF_SIZE_LOG_N } from "../HonkTypes.sol"; import {ecMul, ecAdd, ecSub, negateInplace, convertProofPoint} from "../utils.sol"; // Field arithmetic libraries - prevent littering the code with modmul / addmul -import {Fr, FrLib} from "../Fr.sol"; - -// Transcript library to generate fiat shamir challenges -struct Transcript { - Fr eta; - Fr etaTwo; - Fr etaThree; - Fr beta; - Fr gamma; - Fr[NUMBER_OF_ALPHAS] alphas; - Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; - Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; - Fr rho; - // Zero morph - Fr zmX; - Fr zmY; - Fr zmZ; - Fr zmQuotient; - // Derived - Fr publicInputsDelta; -} - -library TranscriptLib { - function generateTranscript( - Honk.Proof memory proof, - Honk.VerificationKey memory vk, - bytes32[] calldata publicInputs - ) internal view returns (Transcript memory t) { - (t.eta, t.etaTwo, t.etaThree) = generateEtaChallenge(proof, publicInputs); - - (t.beta, t.gamma) = generateBetaAndGammaChallenges(t.etaThree, proof); - - t.alphas = generateAlphaChallenges(t.gamma, proof); - - t.gateChallenges = generateGateChallenges(t.alphas[NUMBER_OF_ALPHAS - 1]); - - t.sumCheckUChallenges = generateSumcheckChallenges(proof, t.gateChallenges[CONST_PROOF_SIZE_LOG_N - 1]); - t.rho = generateRhoChallenge(proof, t.sumCheckUChallenges[CONST_PROOF_SIZE_LOG_N - 1]); - - t.zmY = generateZMYChallenge(t.rho, proof); - - (t.zmX, t.zmZ) = generateZMXZChallenges(t.zmY, proof); - - return t; - } - - function generateEtaChallenge(Honk.Proof memory proof, bytes32[] calldata publicInputs) - internal - view - returns (Fr eta, Fr etaTwo, Fr etaThree) - { - bytes32[3 + NUMBER_OF_PUBLIC_INPUTS + 12] memory round0; - round0[0] = bytes32(proof.circuitSize); - round0[1] = bytes32(proof.publicInputsSize); - round0[2] = bytes32(proof.publicInputsOffset); - for (uint256 i = 0; i < NUMBER_OF_PUBLIC_INPUTS; i++) { - round0[3 + i] = bytes32(publicInputs[i]); - } - - // Create the first challenge - // Note: w4 is added to the challenge later on - round0[3 + NUMBER_OF_PUBLIC_INPUTS] = bytes32(proof.w1.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 1] = bytes32(proof.w1.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 2] = bytes32(proof.w1.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 3] = bytes32(proof.w1.y_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 4] = bytes32(proof.w2.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 5] = bytes32(proof.w2.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 6] = bytes32(proof.w2.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 7] = bytes32(proof.w2.y_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 8] = bytes32(proof.w3.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 9] = bytes32(proof.w3.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 10] = bytes32(proof.w3.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 11] = bytes32(proof.w3.y_1); - - eta = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); - etaTwo = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(eta)))); - etaThree = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(etaTwo)))); - } - - function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr beta, Fr gamma) - { - bytes32[13] memory round1; - round1[0] = FrLib.toBytes32(previousChallenge); - round1[1] = bytes32(proof.lookupReadCounts.x_0); - round1[2] = bytes32(proof.lookupReadCounts.x_1); - round1[3] = bytes32(proof.lookupReadCounts.y_0); - round1[4] = bytes32(proof.lookupReadCounts.y_1); - round1[5] = bytes32(proof.lookupReadTags.x_0); - round1[6] = bytes32(proof.lookupReadTags.x_1); - round1[7] = bytes32(proof.lookupReadTags.y_0); - round1[8] = bytes32(proof.lookupReadTags.y_1); - round1[9] = bytes32(proof.w4.x_0); - round1[10] = bytes32(proof.w4.x_1); - round1[11] = bytes32(proof.w4.y_0); - round1[12] = bytes32(proof.w4.y_1); - - beta = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); - gamma = FrLib.fromBytes32(keccak256(abi.encodePacked(beta))); - } - - // Alpha challenges non-linearise the gate contributions - function generateAlphaChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr[NUMBER_OF_ALPHAS] memory alphas) - { - // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup - uint256[9] memory alpha0; - alpha0[0] = Fr.unwrap(previousChallenge); - alpha0[1] = proof.lookupInverses.x_0; - alpha0[2] = proof.lookupInverses.x_1; - alpha0[3] = proof.lookupInverses.y_0; - alpha0[4] = proof.lookupInverses.y_1; - alpha0[5] = proof.zPerm.x_0; - alpha0[6] = proof.zPerm.x_1; - alpha0[7] = proof.zPerm.y_0; - alpha0[8] = proof.zPerm.y_1; - - alphas[0] = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); - - Fr prevChallenge = alphas[0]; - for (uint256 i = 1; i < NUMBER_OF_ALPHAS; i++) { - prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(prevChallenge)))); - alphas[i] = prevChallenge; - } - } - - function generateGateChallenges(Fr previousChallenge) - internal - view - returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges) - { - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); - gateChallenges[i] = previousChallenge; - } - } - - function generateSumcheckChallenges(Honk.Proof memory proof, Fr prevChallenge) - internal - view - returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges) - { - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - Fr[BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; - univariateChal[0] = prevChallenge; - - // TODO(opt): memcpy - for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { - univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; - } +import {MODULUS as P, MINUS_ONE, Fr, FrLib} from "../Fr.sol"; - sumcheckChallenges[i] = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); - prevChallenge = sumcheckChallenges[i]; - } - } - - function generateRhoChallenge(Honk.Proof memory proof, Fr prevChallenge) internal view returns (Fr rho) { - Fr[NUMBER_OF_ENTITIES + 1] memory rhoChallengeElements; - rhoChallengeElements[0] = prevChallenge; +import {Transcript, TranscriptLib} from "../Transcript.sol"; - // TODO: memcpy - for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { - rhoChallengeElements[i + 1] = proof.sumcheckEvaluations[i]; - } - - rho = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); - } - - function generateZMYChallenge(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr zeromorphY) - { - uint256[CONST_PROOF_SIZE_LOG_N * 4 + 1] memory zmY; - zmY[0] = Fr.unwrap(previousChallenge); - - for (uint256 i; i < CONST_PROOF_SIZE_LOG_N; ++i) { - zmY[1 + i * 4] = proof.zmCqs[i].x_0; - zmY[2 + i * 4] = proof.zmCqs[i].x_1; - zmY[3 + i * 4] = proof.zmCqs[i].y_0; - zmY[4 + i * 4] = proof.zmCqs[i].y_1; - } - - zeromorphY = FrLib.fromBytes32(keccak256(abi.encodePacked(zmY))); - } - - function generateZMXZChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr zeromorphX, Fr zeromorphZ) - { - uint256[4 + 1] memory buf; - buf[0] = Fr.unwrap(previousChallenge); - - buf[1] = proof.zmCq.x_0; - buf[2] = proof.zmCq.x_1; - buf[3] = proof.zmCq.y_0; - buf[4] = proof.zmCq.y_1; - - zeromorphX = FrLib.fromBytes32(keccak256(abi.encodePacked(buf))); - zeromorphZ = FrLib.fromBytes32(keccak256(abi.encodePacked(zeromorphX))); - } -} +import {RelationsLib} from "../Relations.sol"; // Errors error PublicInputsLengthWrong(); @@ -235,18 +32,16 @@ error ZeromorphFailed(); /// Smart contract verifier of honk proofs contract BlakeHonkVerifier is IVerifier { - Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) - function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) { Honk.VerificationKey memory vk = loadVerificationKey(); - Honk.Proof memory p = loadProof(proof); + Honk.Proof memory p = TranscriptLib.loadProof(proof); if (publicInputs.length != vk.publicInputsSize) { revert PublicInputsLengthWrong(); } // Generate the fiat shamir challenges for the whole protocol - Transcript memory t = TranscriptLib.generateTranscript(p, vk, publicInputs); + Transcript memory t = TranscriptLib.generateTranscript(p, publicInputs, vk.publicInputsSize); // Compute the public input delta t.publicInputsDelta = @@ -267,138 +62,6 @@ contract BlakeHonkVerifier is IVerifier { return VK.loadVerificationKey(); } - // TODO: mod q proof points - // TODO: Preprocess all of the memory locations - // TODO: Adjust proof point serde away from poseidon forced field elements - function loadProof(bytes calldata proof) internal view returns (Honk.Proof memory) { - Honk.Proof memory p; - - // Metadata - p.circuitSize = uint256(bytes32(proof[0x00:0x20])); - p.publicInputsSize = uint256(bytes32(proof[0x20:0x40])); - p.publicInputsOffset = uint256(bytes32(proof[0x40:0x60])); - - // Commitments - p.w1 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x60:0x80])), - x_1: uint256(bytes32(proof[0x80:0xa0])), - y_0: uint256(bytes32(proof[0xa0:0xc0])), - y_1: uint256(bytes32(proof[0xc0:0xe0])) - }); - - p.w2 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0xe0:0x100])), - x_1: uint256(bytes32(proof[0x100:0x120])), - y_0: uint256(bytes32(proof[0x120:0x140])), - y_1: uint256(bytes32(proof[0x140:0x160])) - }); - p.w3 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x160:0x180])), - x_1: uint256(bytes32(proof[0x180:0x1a0])), - y_0: uint256(bytes32(proof[0x1a0:0x1c0])), - y_1: uint256(bytes32(proof[0x1c0:0x1e0])) - }); - - // Lookup / Permutation Helper Commitments - p.lookupReadCounts = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x1e0:0x200])), - x_1: uint256(bytes32(proof[0x200:0x220])), - y_0: uint256(bytes32(proof[0x220:0x240])), - y_1: uint256(bytes32(proof[0x240:0x260])) - }); - p.lookupReadTags = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x260:0x280])), - x_1: uint256(bytes32(proof[0x280:0x2a0])), - y_0: uint256(bytes32(proof[0x2a0:0x2c0])), - y_1: uint256(bytes32(proof[0x2c0:0x2e0])) - }); - p.w4 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x2e0:0x300])), - x_1: uint256(bytes32(proof[0x300:0x320])), - y_0: uint256(bytes32(proof[0x320:0x340])), - y_1: uint256(bytes32(proof[0x340:0x360])) - }); - p.lookupInverses = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x360:0x380])), - x_1: uint256(bytes32(proof[0x380:0x3a0])), - y_0: uint256(bytes32(proof[0x3a0:0x3c0])), - y_1: uint256(bytes32(proof[0x3c0:0x3e0])) - }); - p.zPerm = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x3e0:0x400])), - x_1: uint256(bytes32(proof[0x400:0x420])), - y_0: uint256(bytes32(proof[0x420:0x440])), - y_1: uint256(bytes32(proof[0x440:0x460])) - }); - - // TEMP the boundary of what has already been read - uint256 boundary = 0x460; - - // Sumcheck univariates - // TODO: in this case we know what log_n is - so we hard code it, we would want this to be included in - // a cpp template for different circuit sizes - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - // The loop boundary of i, this will shift forward on each evaluation - uint256 loop_boundary = boundary + (i * 0x20 * BATCHED_RELATION_PARTIAL_LENGTH); - - for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { - uint256 start = loop_boundary + (j * 0x20); - uint256 end = start + 0x20; - p.sumcheckUnivariates[i][j] = FrLib.fromBytes32(bytes32(proof[start:end])); - } - } - - boundary = boundary + (CONST_PROOF_SIZE_LOG_N * BATCHED_RELATION_PARTIAL_LENGTH * 0x20); - // Sumcheck evaluations - for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { - uint256 start = boundary + (i * 0x20); - uint256 end = start + 0x20; - p.sumcheckEvaluations[i] = FrLib.fromBytes32(bytes32(proof[start:end])); - } - - boundary = boundary + (NUMBER_OF_ENTITIES * 0x20); - // Zero morph Commitments - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - // Explicitly stating the x0, x1, y0, y1 start and end boundaries to make the calldata slicing bearable - uint256 xStart = boundary + (i * 0x80); - uint256 xEnd = xStart + 0x20; - - uint256 x1Start = xEnd; - uint256 x1End = x1Start + 0x20; - - uint256 yStart = x1End; - uint256 yEnd = yStart + 0x20; - - uint256 y1Start = yEnd; - uint256 y1End = y1Start + 0x20; - - p.zmCqs[i] = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[xStart:xEnd])), - x_1: uint256(bytes32(proof[x1Start:x1End])), - y_0: uint256(bytes32(proof[yStart:yEnd])), - y_1: uint256(bytes32(proof[y1Start:y1End])) - }); - } - - boundary = boundary + (CONST_PROOF_SIZE_LOG_N * 0x80); - - p.zmCq = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[boundary:boundary + 0x20])), - x_1: uint256(bytes32(proof[boundary + 0x20:boundary + 0x40])), - y_0: uint256(bytes32(proof[boundary + 0x40:boundary + 0x60])), - y_1: uint256(bytes32(proof[boundary + 0x60:boundary + 0x80])) - }); - - p.zmPi = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[boundary + 0x80:boundary + 0xa0])), - x_1: uint256(bytes32(proof[boundary + 0xa0:boundary + 0xc0])), - y_0: uint256(bytes32(proof[boundary + 0xc0:boundary + 0xe0])), - y_1: uint256(bytes32(proof[boundary + 0xe0:boundary + 0x100])) - }); - - return p; - } - function computePublicInputDelta( bytes32[] memory publicInputs, Fr beta, @@ -448,7 +111,7 @@ contract BlakeHonkVerifier is IVerifier { } // Last round - Fr grandHonkRelationSum = accumulateRelationEvaluations(proof, tp, powPartialEvaluation); + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations(proof, tp, powPartialEvaluation); verified = (grandHonkRelationSum == roundTarget); } @@ -468,18 +131,27 @@ contract BlakeHonkVerifier is IVerifier { returns (Fr targetSum) { // TODO: inline - Fr[7] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000002d0), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff89), - Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000030), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffdd), - Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000030), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff89), - Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000002d0) + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff11), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000090), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff71), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000000f0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000013b0) ]; - Fr[7] memory BARYCENTRIC_DOMAIN = - [Fr.wrap(0x00), Fr.wrap(0x01), Fr.wrap(0x02), Fr.wrap(0x03), Fr.wrap(0x04), Fr.wrap(0x05), Fr.wrap(0x06)]; + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_DOMAIN = [ + Fr.wrap(0x00), + Fr.wrap(0x01), + Fr.wrap(0x02), + Fr.wrap(0x03), + Fr.wrap(0x04), + Fr.wrap(0x05), + Fr.wrap(0x06), + Fr.wrap(0x07) + ]; // To compute the next target sum, we evaluate the given univariate at a point u (challenge). // TODO: opt: use same array mem for each iteratioon @@ -512,590 +184,13 @@ contract BlakeHonkVerifier is IVerifier { // Univariate evaluation of the monomial ((1-X_l) + X_l.B_l) at the challenge point X_l=u_l function partiallyEvaluatePOW(Transcript memory tp, Fr currentEvaluation, Fr roundChallenge, uint256 round) internal - view + pure returns (Fr newEvaluation) { Fr univariateEval = Fr.wrap(1) + (roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); newEvaluation = currentEvaluation * univariateEval; } - // Calculate the contributions of each relation to the expected value of the full honk relation - // - // For each relation, we use the purported values ( the ones provided by the prover ) of the multivariates to - // calculate a contribution to the purported value of the full Honk relation. - // These are stored in the evaluations part of the proof object. - // We add these together, with the appropiate scaling factor ( the alphas calculated in challenges ) - // This value is checked against the final value of the target total sum - et voila! - function accumulateRelationEvaluations(Honk.Proof memory proof, Transcript memory tp, Fr powPartialEval) - internal - view - returns (Fr accumulator) - { - Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations = proof.sumcheckEvaluations; - Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; - - // Accumulate all 6 custom gates - each with varying number of subrelations - accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); - accumulatePermutationRelation(purportedEvaluations, tp, evaluations, powPartialEval); - accumulateLogDerivativeLookupRelation(purportedEvaluations, tp, evaluations, powPartialEval); - accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); - accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); - accumulateAuxillaryRelation(purportedEvaluations, tp, evaluations, powPartialEval); - - // Apply alpha challenges to challenge evaluations - // Returns grand honk realtion evaluation - accumulator = scaleAndBatchSubrelations(evaluations, tp.alphas); - } - - /** - * WIRE - * - * Wire is an aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids - * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code - * editors, and thus is noisy. - */ - function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { - return p[uint256(_wire)]; - } - - /** - * Ultra Arithmetic Relation - * - */ - function accumulateArithmeticRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - // Relation 0 - Fr q_arith = wire(p, WIRE.Q_ARITH); - { - Fr neg_half = Fr.wrap(0) - (FrLib.invert(Fr.wrap(2))); - - Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; - accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) - + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); - accum = accum + (q_arith - Fr.wrap(1)) * wire(p, WIRE.W_4_SHIFT); - accum = accum * q_arith; - accum = accum * domainSep; - evals[0] = accum; - } - - // Relation 1 - { - Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); - accum = accum * (q_arith - Fr.wrap(2)); - accum = accum * (q_arith - Fr.wrap(1)); - accum = accum * q_arith; - accum = accum * domainSep; - evals[1] = accum; - } - } - - function accumulatePermutationRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr grand_product_numerator; - Fr grand_product_denominator; - - { - Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * tp.beta + tp.gamma; - num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * tp.beta + tp.gamma); - num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * tp.beta + tp.gamma); - num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * tp.beta + tp.gamma); - - grand_product_numerator = num; - } - { - Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * tp.beta + tp.gamma; - den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * tp.beta + tp.gamma); - den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * tp.beta + tp.gamma); - den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * tp.beta + tp.gamma); - - grand_product_denominator = den; - } - - // Contribution 2 - { - Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; - - acc = acc - - ( - (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * tp.publicInputsDelta)) - * grand_product_denominator - ); - acc = acc * domainSep; - evals[2] = acc; - } - - // Contribution 3 - { - Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; - evals[3] = acc; - } - } - - function accumulateLogDerivativeLookupRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr write_term; - Fr read_term; - - // Calculate the write term (the table accumulation) - { - write_term = wire(p, WIRE.TABLE_1) + tp.gamma + (wire(p, WIRE.TABLE_2) * tp.eta) - + (wire(p, WIRE.TABLE_3) * tp.etaTwo) + (wire(p, WIRE.TABLE_4) * tp.etaThree); - } - - // Calculate the write term - { - Fr derived_entry_1 = wire(p, WIRE.W_L) + tp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); - Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); - Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); - - read_term = derived_entry_1 + (derived_entry_2 * tp.eta) + (derived_entry_3 * tp.etaTwo) - + (wire(p, WIRE.Q_O) * tp.etaThree); - } - - Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; - Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; - - Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) - - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); - - // Inverse calculated correctly relation - Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; - accumulatorNone = accumulatorNone * domainSep; - - // Inverse - Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; - - evals[4] = accumulatorNone; - evals[5] = accumulatorOne; - } - - function accumulateDeltaRangeRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr minus_one = Fr.wrap(0) - Fr.wrap(1); - Fr minus_two = Fr.wrap(0) - Fr.wrap(2); - Fr minus_three = Fr.wrap(0) - Fr.wrap(3); - - // Compute wire differences - Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); - Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); - Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); - Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); - - // Contribution 6 - { - Fr acc = delta_1; - acc = acc * (delta_1 + minus_one); - acc = acc * (delta_1 + minus_two); - acc = acc * (delta_1 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[6] = acc; - } - - // Contribution 7 - { - Fr acc = delta_2; - acc = acc * (delta_2 + minus_one); - acc = acc * (delta_2 + minus_two); - acc = acc * (delta_2 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[7] = acc; - } - - // Contribution 8 - { - Fr acc = delta_3; - acc = acc * (delta_3 + minus_one); - acc = acc * (delta_3 + minus_two); - acc = acc * (delta_3 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[8] = acc; - } - - // Contribution 9 - { - Fr acc = delta_4; - acc = acc * (delta_4 + minus_one); - acc = acc * (delta_4 + minus_two); - acc = acc * (delta_4 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[9] = acc; - } - } - - struct EllipticParams { - // Points - Fr x_1; - Fr y_1; - Fr x_2; - Fr y_2; - Fr y_3; - Fr x_3; - // push accumulators into memory - Fr x_double_identity; - } - - function accumulateEllipticRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - EllipticParams memory ep; - ep.x_1 = wire(p, WIRE.W_R); - ep.y_1 = wire(p, WIRE.W_O); - - ep.x_2 = wire(p, WIRE.W_L_SHIFT); - ep.y_2 = wire(p, WIRE.W_4_SHIFT); - ep.y_3 = wire(p, WIRE.W_O_SHIFT); - ep.x_3 = wire(p, WIRE.W_R_SHIFT); - - Fr q_sign = wire(p, WIRE.Q_L); - Fr q_is_double = wire(p, WIRE.Q_M); - - // Contribution 10 point addition, x-coordinate check - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - Fr x_diff = (ep.x_2 - ep.x_1); - Fr y1_sqr = (ep.y_1 * ep.y_1); - { - // Move to top - Fr partialEval = domainSep; - - Fr y2_sqr = (ep.y_2 * ep.y_2); - Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; - Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); - x_add_identity = x_add_identity * x_diff * x_diff; - x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; - - evals[10] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (Fr.wrap(1) - q_is_double); - } - - // Contribution 11 point addition, x-coordinate check - // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 - { - Fr y1_plus_y3 = ep.y_1 + ep.y_3; - Fr y_diff = ep.y_2 * q_sign - ep.y_1; - Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; - evals[11] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (Fr.wrap(1) - q_is_double); - } - - // Contribution 10 point doubling, x-coordinate check - // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 - // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 - { - Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; - Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; - y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; - Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); - - // NOTE: pushed into memory (stack >:'( ) - ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; - - Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; - evals[10] = evals[10] + acc; - } - - // Contribution 11 point doubling, y-coordinate check - // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 - { - Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; - Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); - evals[11] = evals[11] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; - } - } - - // Constants for the auxiliary relation - Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); - Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); - Fr constant MINUS_ONE = Fr.wrap(P - 1); - - // Parameters used within the Auxiliary Relation - // A struct is used to work around stack too deep. This relation has alot of variables - struct AuxParams { - Fr limb_subproduct; - Fr non_native_field_gate_1; - Fr non_native_field_gate_2; - Fr non_native_field_gate_3; - Fr limb_accumulator_1; - Fr limb_accumulator_2; - Fr memory_record_check; - Fr partial_record_check; - Fr next_gate_access_type; - Fr record_delta; - Fr index_delta; - Fr adjacent_values_match_if_adjacent_indices_match; - Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; - Fr access_check; - Fr next_gate_access_type_is_boolean; - Fr ROM_consistency_check_identity; - Fr RAM_consistency_check_identity; - Fr timestamp_delta; - Fr RAM_timestamp_check_identity; - Fr memory_identity; - Fr index_is_monotonically_increasing; - Fr auxiliary_identity; - } - - function accumulateAuxillaryRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal pure { - AuxParams memory ap; - - /** - * Contribution 12 - * Non native field arithmetic gate 2 - * deg 4 - * - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - * - */ - ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); - ap.non_native_field_gate_2 = - (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); - - ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; - ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); - ap.non_native_field_gate_1 = ap.limb_subproduct; - ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); - ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); - - ap.non_native_field_gate_3 = ap.limb_subproduct; - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); - - Fr non_native_field_identity = - ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; - non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); - - // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm - // deg 2 - ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); - ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); - - // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm - // deg 2 - ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); - ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); - - Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; - limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 - - /** - * MEMORY - * - * A RAM memory record contains a tuple of the following fields: - * * i: `index` of memory cell being accessed - * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) - * * v: `value` of memory cell being accessed - * * a: `access` type of record. read: 0 = read, 1 = write - * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three - * - * A ROM memory record contains a tuple of the following fields: - * * i: `index` of memory cell being accessed - * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) - * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) - * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three - * - * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + - * selectors, depending on whether the gate is a RAM read/write or a ROM read - * - * | gate type | i | v2/t | v | a | r | - * | --------- | -- | ----- | -- | -- | -- | - * | ROM | w1 | w2 | w3 | -- | w4 | - * | RAM | w1 | w2 | w3 | qc | w4 | - * - * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on - * `w2` to fix its value) - * - * - */ - - /** - * Memory Record Check - * Partial degree: 1 - * Total degree: 4 - * - * A ROM/ROM access gate can be evaluated with the identity: - * - * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 - * - * For ROM gates, qc = 0 - */ - ap.memory_record_check = wire(p, WIRE.W_O) * tp.etaThree; - ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * tp.etaTwo); - ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * tp.eta); - ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); - ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 - ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); - - /** - * Contribution 13 & 14 - * ROM Consistency Check - * Partial degree: 1 - * Total degree: 4 - * - * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of - * records that are sorted. - * - * We apply the following checks for the sorted records: - * - * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 - * 2. index values for adjacent records are monotonically increasing - * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} - * - */ - ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); - ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); - - ap.index_is_monotonically_increasing = ap.index_delta * ap.index_delta - ap.index_delta; // deg 2 - - ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + Fr.wrap(1)) * ap.record_delta; // deg 2 - - evals[13] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) - * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 - evals[14] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) - * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 - - ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 - - /** - * Contributions 15,16,17 - * RAM Consistency Check - * - * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` - * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. - * This is validated by requiring `access` to be boolean - * - * For two adjacent entries in the sorted list if _both_ - * A) index values match - * B) adjacent access value is 0 (i.e. next gate is a READ) - * then - * C) both values must match. - * The gate boolean check is - * (A && B) => C === !(A && B) || C === !A || !B || C - * - * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized - * with a WRITE operation. - */ - Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 - ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 - - // TODO(https://github.com/AztecProtocol/barretenberg/issues/757): If we sorted in - // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta - // deg 1 or 4 - ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * tp.etaThree; - ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * tp.etaTwo); - ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * tp.eta); - ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; - - Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); - ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = ( - ap.index_delta * MINUS_ONE + Fr.wrap(1) - ) * value_delta * (ap.next_gate_access_type * MINUS_ONE + Fr.wrap(1)); // deg 3 or 6 - - // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the - // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't - // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access - // type is correct, to cover this edge case - // deg 2 or 4 - ap.next_gate_access_type_is_boolean = - ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; - - // Putting it all together... - evals[15] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation - * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 or 8 - evals[16] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 - evals[17] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 6 - - ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9 - - /** - * RAM Timestamp Consistency Check - * - * | w1 | w2 | w3 | w4 | - * | index | timestamp | timestamp_check | -- | - * - * Let delta_index = index_{i + 1} - index_{i} - * - * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i - * Else timestamp_check = 0 - */ - ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); - ap.RAM_timestamp_check_identity = - (ap.index_delta * MINUS_ONE + Fr.wrap(1)) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 - - /** - * Complete Contribution 12 - * The complete RAM/ROM memory identity - * Partial degree: - */ - ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 - ap.memory_identity = - ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 - ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 - ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 - - // (deg 3 or 9) + (deg 4) + (deg 3) - ap.auxiliary_identity = ap.memory_identity + non_native_field_identity + limb_accumulator_identity; - ap.auxiliary_identity = ap.auxiliary_identity * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 10 - evals[12] = ap.auxiliary_identity; - } - - function scaleAndBatchSubrelations( - Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, - Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges - ) internal view returns (Fr accumulator) { - accumulator = accumulator + evaluations[0]; - - for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { - accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; - } - } - function verifyZeroMorph(Honk.Proof memory proof, Honk.VerificationKey memory vk, Transcript memory tp) internal view @@ -1117,6 +212,7 @@ contract BlakeHonkVerifier is IVerifier { Honk.G1Point memory c_zeta_Z = ecAdd(c_zeta, ecMul(c_zeta_x, tp.zmZ)); // KZG pairing accumulator + // WORKTODO: concerned that this is zero - it is multiplied by a point later on Fr evaluation = Fr.wrap(0); verified = zkgReduceVerify(proof, tp, evaluation, c_zeta_Z); } @@ -1181,12 +277,12 @@ contract BlakeHonkVerifier is IVerifier { // f commitments are accumulated at (zm_x * r) cp.rho_pow = Fr.wrap(1); - for (uint256 i = 1; i < 34; ++i) { + for (uint256 i = 1; i <= NUMBER_UNSHIFTED; ++i) { scalars[i] = tp.zmX * cp.rho_pow; cp.rho_pow = cp.rho_pow * tp.rho; } // g commitments are accumulated at r - for (uint256 i = 34; i < 43; ++i) { + for (uint256 i = NUMBER_UNSHIFTED + 1; i <= NUMBER_OF_ENTITIES; ++i) { scalars[i] = cp.rho_pow; cp.rho_pow = cp.rho_pow * tp.rho; } @@ -1203,41 +299,43 @@ contract BlakeHonkVerifier is IVerifier { commitments[9] = vk.qElliptic; commitments[10] = vk.qAux; commitments[11] = vk.qLookup; - commitments[12] = vk.s1; - commitments[13] = vk.s2; - commitments[14] = vk.s3; - commitments[15] = vk.s4; - commitments[16] = vk.id1; - commitments[17] = vk.id2; - commitments[18] = vk.id3; - commitments[19] = vk.id4; - commitments[20] = vk.t1; - commitments[21] = vk.t2; - commitments[22] = vk.t3; - commitments[23] = vk.t4; - commitments[24] = vk.lagrangeFirst; - commitments[25] = vk.lagrangeLast; + commitments[12] = vk.qPoseidon2External; + commitments[13] = vk.qPoseidon2Internal; + commitments[14] = vk.s1; + commitments[15] = vk.s2; + commitments[16] = vk.s3; + commitments[17] = vk.s4; + commitments[18] = vk.id1; + commitments[19] = vk.id2; + commitments[20] = vk.id3; + commitments[21] = vk.id4; + commitments[22] = vk.t1; + commitments[23] = vk.t2; + commitments[24] = vk.t3; + commitments[25] = vk.t4; + commitments[26] = vk.lagrangeFirst; + commitments[27] = vk.lagrangeLast; // Accumulate proof points - commitments[26] = convertProofPoint(proof.w1); - commitments[27] = convertProofPoint(proof.w2); - commitments[28] = convertProofPoint(proof.w3); - commitments[29] = convertProofPoint(proof.w4); - commitments[30] = convertProofPoint(proof.zPerm); - commitments[31] = convertProofPoint(proof.lookupInverses); - commitments[32] = convertProofPoint(proof.lookupReadCounts); - commitments[33] = convertProofPoint(proof.lookupReadTags); + commitments[28] = convertProofPoint(proof.w1); + commitments[29] = convertProofPoint(proof.w2); + commitments[30] = convertProofPoint(proof.w3); + commitments[31] = convertProofPoint(proof.w4); + commitments[32] = convertProofPoint(proof.zPerm); + commitments[33] = convertProofPoint(proof.lookupInverses); + commitments[34] = convertProofPoint(proof.lookupReadCounts); + commitments[35] = convertProofPoint(proof.lookupReadTags); // to be Shifted - commitments[34] = vk.t1; - commitments[35] = vk.t2; - commitments[36] = vk.t3; - commitments[37] = vk.t4; - commitments[38] = convertProofPoint(proof.w1); - commitments[39] = convertProofPoint(proof.w2); - commitments[40] = convertProofPoint(proof.w3); - commitments[41] = convertProofPoint(proof.w4); - commitments[42] = convertProofPoint(proof.zPerm); + commitments[36] = vk.t1; + commitments[37] = vk.t2; + commitments[38] = vk.t3; + commitments[39] = vk.t4; + commitments[40] = convertProofPoint(proof.w1); + commitments[41] = convertProofPoint(proof.w2); + commitments[42] = convertProofPoint(proof.w3); + commitments[43] = convertProofPoint(proof.w4); + commitments[44] = convertProofPoint(proof.zPerm); // Add scalar contributions // Add contributions: scalar * [q_k], k = 0,...,log_N, where @@ -1262,8 +360,8 @@ contract BlakeHonkVerifier is IVerifier { cp.x_pow_2kp1 = cp.x_pow_2kp1 * cp.x_pow_2kp1; } - scalars[43 + k] = scalar; - commitments[43 + k] = convertProofPoint(proof.zmCqs[k]); + scalars[NUMBER_OF_ENTITIES + 1 + k] = scalar; + commitments[NUMBER_OF_ENTITIES + 1 + k] = convertProofPoint(proof.zmCqs[k]); } return batchMul2(commitments, scalars); @@ -1282,7 +380,7 @@ contract BlakeHonkVerifier is IVerifier { let free := mload(0x40) // Write the original into the accumulator - // Load into memory for ecMUL, leave offset for eccAdd result + // Load into memory forecMUL, leave offset foreccAdd result // base is an array of pointers, so we have to dereference them mstore(add(free, 0x40), mload(mload(base))) mstore(add(free, 0x60), mload(add(0x20, mload(base)))) @@ -1322,7 +420,7 @@ contract BlakeHonkVerifier is IVerifier { let free := mload(0x40) // Write the original into the accumulator - // Load into memory for ecMUL, leave offset for eccAdd result + // Load into memory forecMUL, leave offset foreccAdd result // base is an array of pointers, so we have to dereference them mstore(add(free, 0x40), mload(mload(base))) mstore(add(free, 0x60), mload(add(0x20, mload(base)))) diff --git a/barretenberg/sol/src/honk/instance/EcdsaHonk.sol b/barretenberg/sol/src/honk/instance/EcdsaHonk.sol index 92dd87aa01a..1dc716151cd 100644 --- a/barretenberg/sol/src/honk/instance/EcdsaHonk.sol +++ b/barretenberg/sol/src/honk/instance/EcdsaHonk.sol @@ -11,223 +11,19 @@ import { NUMBER_OF_ENTITIES, NUMBER_OF_SUBRELATIONS, NUMBER_OF_ALPHAS, + NUMBER_UNSHIFTED, BATCHED_RELATION_PARTIAL_LENGTH, - CONST_PROOF_SIZE_LOG_N, - P, - Q + CONST_PROOF_SIZE_LOG_N } from "../HonkTypes.sol"; import {ecMul, ecAdd, ecSub, negateInplace, convertProofPoint} from "../utils.sol"; // Field arithmetic libraries - prevent littering the code with modmul / addmul -import {Fr, FrLib} from "../Fr.sol"; - -// Transcript library to generate fiat shamir challenges -struct Transcript { - Fr eta; - Fr etaTwo; - Fr etaThree; - Fr beta; - Fr gamma; - Fr[NUMBER_OF_ALPHAS] alphas; - Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; - Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; - Fr rho; - // Zero morph - Fr zmX; - Fr zmY; - Fr zmZ; - Fr zmQuotient; - // Derived - Fr publicInputsDelta; - Fr lookupGrandProductDelta; -} - -library TranscriptLib { - function generateTranscript( - Honk.Proof memory proof, - Honk.VerificationKey memory vk, - bytes32[] calldata publicInputs - ) internal view returns (Transcript memory t) { - (t.eta, t.etaTwo, t.etaThree) = generateEtaChallenge(proof, publicInputs); - - (t.beta, t.gamma) = generateBetaAndGammaChallenges(t.etaThree, proof); - - t.alphas = generateAlphaChallenges(t.gamma, proof); - - t.gateChallenges = generateGateChallenges(t.alphas[NUMBER_OF_ALPHAS - 1]); - - t.sumCheckUChallenges = generateSumcheckChallenges(proof, t.gateChallenges[CONST_PROOF_SIZE_LOG_N - 1]); - t.rho = generateRhoChallenge(proof, t.sumCheckUChallenges[CONST_PROOF_SIZE_LOG_N - 1]); - - t.zmY = generateZMYChallenge(t.rho, proof); - - (t.zmX, t.zmZ) = generateZMXZChallenges(t.zmY, proof); - - return t; - } - - function generateEtaChallenge(Honk.Proof memory proof, bytes32[] calldata publicInputs) - internal - view - returns (Fr eta, Fr etaTwo, Fr etaThree) - { - bytes32[3 + NUMBER_OF_PUBLIC_INPUTS + 12] memory round0; - round0[0] = bytes32(proof.circuitSize); - round0[1] = bytes32(proof.publicInputsSize); - round0[2] = bytes32(proof.publicInputsOffset); - for (uint256 i = 0; i < NUMBER_OF_PUBLIC_INPUTS; i++) { - round0[3 + i] = bytes32(publicInputs[i]); - } - - // Create the first challenge - // Note: w4 is added to the challenge later on - round0[3 + NUMBER_OF_PUBLIC_INPUTS] = bytes32(proof.w1.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 1] = bytes32(proof.w1.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 2] = bytes32(proof.w1.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 3] = bytes32(proof.w1.y_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 4] = bytes32(proof.w2.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 5] = bytes32(proof.w2.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 6] = bytes32(proof.w2.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 7] = bytes32(proof.w2.y_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 8] = bytes32(proof.w3.x_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 9] = bytes32(proof.w3.x_1); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 10] = bytes32(proof.w3.y_0); - round0[3 + NUMBER_OF_PUBLIC_INPUTS + 11] = bytes32(proof.w3.y_1); - - eta = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); - etaTwo = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(eta)))); - etaThree = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(etaTwo)))); - } - - function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr beta, Fr gamma) - { - bytes32[13] memory round1; - round1[0] = FrLib.toBytes32(previousChallenge); - round1[1] = bytes32(proof.lookupReadCounts.x_0); - round1[2] = bytes32(proof.lookupReadCounts.x_1); - round1[3] = bytes32(proof.lookupReadCounts.y_0); - round1[4] = bytes32(proof.lookupReadCounts.y_1); - round1[5] = bytes32(proof.lookupReadTags.x_0); - round1[6] = bytes32(proof.lookupReadTags.x_1); - round1[7] = bytes32(proof.lookupReadTags.y_0); - round1[8] = bytes32(proof.lookupReadTags.y_1); - round1[9] = bytes32(proof.w4.x_0); - round1[10] = bytes32(proof.w4.x_1); - round1[11] = bytes32(proof.w4.y_0); - round1[12] = bytes32(proof.w4.y_1); - - beta = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); - gamma = FrLib.fromBytes32(keccak256(abi.encodePacked(beta))); - } - - // Alpha challenges non-linearise the gate contributions - function generateAlphaChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr[NUMBER_OF_ALPHAS] memory alphas) - { - // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup - uint256[9] memory alpha0; - alpha0[0] = Fr.unwrap(previousChallenge); - alpha0[1] = proof.lookupInverses.x_0; - alpha0[2] = proof.lookupInverses.x_1; - alpha0[3] = proof.lookupInverses.y_0; - alpha0[4] = proof.lookupInverses.y_1; - alpha0[5] = proof.zPerm.x_0; - alpha0[6] = proof.zPerm.x_1; - alpha0[7] = proof.zPerm.y_0; - alpha0[8] = proof.zPerm.y_1; - - alphas[0] = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); - - Fr prevChallenge = alphas[0]; - for (uint256 i = 1; i < NUMBER_OF_ALPHAS; i++) { - prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(prevChallenge)))); - alphas[i] = prevChallenge; - } - } - - function generateGateChallenges(Fr previousChallenge) - internal - view - returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges) - { - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); - gateChallenges[i] = previousChallenge; - } - } - - function generateSumcheckChallenges(Honk.Proof memory proof, Fr prevChallenge) - internal - view - returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges) - { - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - Fr[BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; - univariateChal[0] = prevChallenge; - - // TODO(opt): memcpy - for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { - univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; - } +import {MODULUS as P, MINUS_ONE, Fr, FrLib} from "../Fr.sol"; - sumcheckChallenges[i] = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); - prevChallenge = sumcheckChallenges[i]; - } - } - - function generateRhoChallenge(Honk.Proof memory proof, Fr prevChallenge) internal view returns (Fr rho) { - Fr[NUMBER_OF_ENTITIES + 1] memory rhoChallengeElements; - rhoChallengeElements[0] = prevChallenge; +import {Transcript, TranscriptLib} from "../Transcript.sol"; - // TODO: memcpy - for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { - rhoChallengeElements[i + 1] = proof.sumcheckEvaluations[i]; - } - - rho = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); - } - - function generateZMYChallenge(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr zeromorphY) - { - uint256[CONST_PROOF_SIZE_LOG_N * 4 + 1] memory zmY; - zmY[0] = Fr.unwrap(previousChallenge); - - for (uint256 i; i < CONST_PROOF_SIZE_LOG_N; ++i) { - zmY[1 + i * 4] = proof.zmCqs[i].x_0; - zmY[2 + i * 4] = proof.zmCqs[i].x_1; - zmY[3 + i * 4] = proof.zmCqs[i].y_0; - zmY[4 + i * 4] = proof.zmCqs[i].y_1; - } - - zeromorphY = FrLib.fromBytes32(keccak256(abi.encodePacked(zmY))); - } - - function generateZMXZChallenges(Fr previousChallenge, Honk.Proof memory proof) - internal - view - returns (Fr zeromorphX, Fr zeromorphZ) - { - uint256[4 + 1] memory buf; - buf[0] = Fr.unwrap(previousChallenge); - - buf[1] = proof.zmCq.x_0; - buf[2] = proof.zmCq.x_1; - buf[3] = proof.zmCq.y_0; - buf[4] = proof.zmCq.y_1; - - zeromorphX = FrLib.fromBytes32(keccak256(abi.encodePacked(buf))); - zeromorphZ = FrLib.fromBytes32(keccak256(abi.encodePacked(zeromorphX))); - } -} +import {RelationsLib} from "../Relations.sol"; // Errors error PublicInputsLengthWrong(); @@ -236,18 +32,16 @@ error ZeromorphFailed(); /// Smart contract verifier of honk proofs contract EcdsaHonkVerifier is IVerifier { - Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) - function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) { Honk.VerificationKey memory vk = loadVerificationKey(); - Honk.Proof memory p = loadProof(proof); + Honk.Proof memory p = TranscriptLib.loadProof(proof); if (publicInputs.length != vk.publicInputsSize) { revert PublicInputsLengthWrong(); } // Generate the fiat shamir challenges for the whole protocol - Transcript memory t = TranscriptLib.generateTranscript(p, vk, publicInputs); + Transcript memory t = TranscriptLib.generateTranscript(p, publicInputs, vk.publicInputsSize); // Compute the public input delta t.publicInputsDelta = @@ -268,138 +62,6 @@ contract EcdsaHonkVerifier is IVerifier { return VK.loadVerificationKey(); } - // TODO: mod q proof points - // TODO: Preprocess all of the memory locations - // TODO: Adjust proof point serde away from poseidon forced field elements - function loadProof(bytes calldata proof) internal view returns (Honk.Proof memory) { - Honk.Proof memory p; - - // Metadata - p.circuitSize = uint256(bytes32(proof[0x00:0x20])); - p.publicInputsSize = uint256(bytes32(proof[0x20:0x40])); - p.publicInputsOffset = uint256(bytes32(proof[0x40:0x60])); - - // Commitments - p.w1 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x60:0x80])), - x_1: uint256(bytes32(proof[0x80:0xa0])), - y_0: uint256(bytes32(proof[0xa0:0xc0])), - y_1: uint256(bytes32(proof[0xc0:0xe0])) - }); - - p.w2 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0xe0:0x100])), - x_1: uint256(bytes32(proof[0x100:0x120])), - y_0: uint256(bytes32(proof[0x120:0x140])), - y_1: uint256(bytes32(proof[0x140:0x160])) - }); - p.w3 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x160:0x180])), - x_1: uint256(bytes32(proof[0x180:0x1a0])), - y_0: uint256(bytes32(proof[0x1a0:0x1c0])), - y_1: uint256(bytes32(proof[0x1c0:0x1e0])) - }); - - // Lookup / Permutation Helper Commitments - p.lookupReadCounts = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x1e0:0x200])), - x_1: uint256(bytes32(proof[0x200:0x220])), - y_0: uint256(bytes32(proof[0x220:0x240])), - y_1: uint256(bytes32(proof[0x240:0x260])) - }); - p.lookupReadTags = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x260:0x280])), - x_1: uint256(bytes32(proof[0x280:0x2a0])), - y_0: uint256(bytes32(proof[0x2a0:0x2c0])), - y_1: uint256(bytes32(proof[0x2c0:0x2e0])) - }); - p.w4 = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x2e0:0x300])), - x_1: uint256(bytes32(proof[0x300:0x320])), - y_0: uint256(bytes32(proof[0x320:0x340])), - y_1: uint256(bytes32(proof[0x340:0x360])) - }); - p.lookupInverses = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x360:0x380])), - x_1: uint256(bytes32(proof[0x380:0x3a0])), - y_0: uint256(bytes32(proof[0x3a0:0x3c0])), - y_1: uint256(bytes32(proof[0x3c0:0x3e0])) - }); - p.zPerm = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[0x3e0:0x400])), - x_1: uint256(bytes32(proof[0x400:0x420])), - y_0: uint256(bytes32(proof[0x420:0x440])), - y_1: uint256(bytes32(proof[0x440:0x460])) - }); - - // TEMP the boundary of what has already been read - uint256 boundary = 0x460; - - // Sumcheck univariates - // TODO: in this case we know what log_n is - so we hard code it, we would want this to be included in - // a cpp template for different circuit sizes - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - // The loop boundary of i, this will shift forward on each evaluation - uint256 loop_boundary = boundary + (i * 0x20 * BATCHED_RELATION_PARTIAL_LENGTH); - - for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) { - uint256 start = loop_boundary + (j * 0x20); - uint256 end = start + 0x20; - p.sumcheckUnivariates[i][j] = FrLib.fromBytes32(bytes32(proof[start:end])); - } - } - - boundary = boundary + (CONST_PROOF_SIZE_LOG_N * BATCHED_RELATION_PARTIAL_LENGTH * 0x20); - // Sumcheck evaluations - for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { - uint256 start = boundary + (i * 0x20); - uint256 end = start + 0x20; - p.sumcheckEvaluations[i] = FrLib.fromBytes32(bytes32(proof[start:end])); - } - - boundary = boundary + (NUMBER_OF_ENTITIES * 0x20); - // Zero morph Commitments - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { - // Explicitly stating the x0, x1, y0, y1 start and end boundaries to make the calldata slicing bearable - uint256 xStart = boundary + (i * 0x80); - uint256 xEnd = xStart + 0x20; - - uint256 x1Start = xEnd; - uint256 x1End = x1Start + 0x20; - - uint256 yStart = x1End; - uint256 yEnd = yStart + 0x20; - - uint256 y1Start = yEnd; - uint256 y1End = y1Start + 0x20; - - p.zmCqs[i] = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[xStart:xEnd])), - x_1: uint256(bytes32(proof[x1Start:x1End])), - y_0: uint256(bytes32(proof[yStart:yEnd])), - y_1: uint256(bytes32(proof[y1Start:y1End])) - }); - } - - boundary = boundary + (CONST_PROOF_SIZE_LOG_N * 0x80); - - p.zmCq = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[boundary:boundary + 0x20])), - x_1: uint256(bytes32(proof[boundary + 0x20:boundary + 0x40])), - y_0: uint256(bytes32(proof[boundary + 0x40:boundary + 0x60])), - y_1: uint256(bytes32(proof[boundary + 0x60:boundary + 0x80])) - }); - - p.zmPi = Honk.G1ProofPoint({ - x_0: uint256(bytes32(proof[boundary + 0x80:boundary + 0xa0])), - x_1: uint256(bytes32(proof[boundary + 0xa0:boundary + 0xc0])), - y_0: uint256(bytes32(proof[boundary + 0xc0:boundary + 0xe0])), - y_1: uint256(bytes32(proof[boundary + 0xe0:boundary + 0x100])) - }); - - return p; - } - function computePublicInputDelta( bytes32[] memory publicInputs, Fr beta, @@ -449,7 +111,7 @@ contract EcdsaHonkVerifier is IVerifier { } // Last round - Fr grandHonkRelationSum = accumulateRelationEvaluations(proof, tp, powPartialEvaluation); + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations(proof, tp, powPartialEvaluation); verified = (grandHonkRelationSum == roundTarget); } @@ -469,18 +131,27 @@ contract EcdsaHonkVerifier is IVerifier { returns (Fr targetSum) { // TODO: inline - Fr[7] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000002d0), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff89), - Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000030), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffdd), - Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000030), - Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff89), - Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000002d0) + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff11), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000090), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff71), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000000f0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000013b0) ]; - Fr[7] memory BARYCENTRIC_DOMAIN = - [Fr.wrap(0x00), Fr.wrap(0x01), Fr.wrap(0x02), Fr.wrap(0x03), Fr.wrap(0x04), Fr.wrap(0x05), Fr.wrap(0x06)]; + Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_DOMAIN = [ + Fr.wrap(0x00), + Fr.wrap(0x01), + Fr.wrap(0x02), + Fr.wrap(0x03), + Fr.wrap(0x04), + Fr.wrap(0x05), + Fr.wrap(0x06), + Fr.wrap(0x07) + ]; // To compute the next target sum, we evaluate the given univariate at a point u (challenge). // TODO: opt: use same array mem for each iteratioon @@ -513,590 +184,13 @@ contract EcdsaHonkVerifier is IVerifier { // Univariate evaluation of the monomial ((1-X_l) + X_l.B_l) at the challenge point X_l=u_l function partiallyEvaluatePOW(Transcript memory tp, Fr currentEvaluation, Fr roundChallenge, uint256 round) internal - view + pure returns (Fr newEvaluation) { Fr univariateEval = Fr.wrap(1) + (roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); newEvaluation = currentEvaluation * univariateEval; } - // Calculate the contributions of each relation to the expected value of the full honk relation - // - // For each relation, we use the purported values ( the ones provided by the prover ) of the multivariates to - // calculate a contribution to the purported value of the full Honk relation. - // These are stored in the evaluations part of the proof object. - // We add these together, with the appropiate scaling factor ( the alphas calculated in challenges ) - // This value is checked against the final value of the target total sum - et voila! - function accumulateRelationEvaluations(Honk.Proof memory proof, Transcript memory tp, Fr powPartialEval) - internal - view - returns (Fr accumulator) - { - Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations = proof.sumcheckEvaluations; - Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; - - // Accumulate all 6 custom gates - each with varying number of subrelations - accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); - accumulatePermutationRelation(purportedEvaluations, tp, evaluations, powPartialEval); - accumulateLogDerivativeLookupRelation(purportedEvaluations, tp, evaluations, powPartialEval); - accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); - accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); - accumulateAuxillaryRelation(purportedEvaluations, tp, evaluations, powPartialEval); - - // Apply alpha challenges to challenge evaluations - // Returns grand honk realtion evaluation - accumulator = scaleAndBatchSubrelations(evaluations, tp.alphas); - } - - /** - * WIRE - * - * Wire is an aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids - * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code - * editors, and thus is noisy. - */ - function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { - return p[uint256(_wire)]; - } - - /** - * Ultra Arithmetic Relation - * - */ - function accumulateArithmeticRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - // Relation 0 - Fr q_arith = wire(p, WIRE.Q_ARITH); - { - Fr neg_half = Fr.wrap(0) - (FrLib.invert(Fr.wrap(2))); - - Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; - accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) - + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); - accum = accum + (q_arith - Fr.wrap(1)) * wire(p, WIRE.W_4_SHIFT); - accum = accum * q_arith; - accum = accum * domainSep; - evals[0] = accum; - } - - // Relation 1 - { - Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); - accum = accum * (q_arith - Fr.wrap(2)); - accum = accum * (q_arith - Fr.wrap(1)); - accum = accum * q_arith; - accum = accum * domainSep; - evals[1] = accum; - } - } - - function accumulatePermutationRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr grand_product_numerator; - Fr grand_product_denominator; - - { - Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * tp.beta + tp.gamma; - num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * tp.beta + tp.gamma); - num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * tp.beta + tp.gamma); - num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * tp.beta + tp.gamma); - - grand_product_numerator = num; - } - { - Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * tp.beta + tp.gamma; - den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * tp.beta + tp.gamma); - den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * tp.beta + tp.gamma); - den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * tp.beta + tp.gamma); - - grand_product_denominator = den; - } - - // Contribution 2 - { - Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; - - acc = acc - - ( - (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * tp.publicInputsDelta)) - * grand_product_denominator - ); - acc = acc * domainSep; - evals[2] = acc; - } - - // Contribution 3 - { - Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; - evals[3] = acc; - } - } - - function accumulateLogDerivativeLookupRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr write_term; - Fr read_term; - - // Calculate the write term (the table accumulation) - { - write_term = wire(p, WIRE.TABLE_1) + tp.gamma + (wire(p, WIRE.TABLE_2) * tp.eta) - + (wire(p, WIRE.TABLE_3) * tp.etaTwo) + (wire(p, WIRE.TABLE_4) * tp.etaThree); - } - - // Calculate the write term - { - Fr derived_entry_1 = wire(p, WIRE.W_L) + tp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); - Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); - Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); - - read_term = derived_entry_1 + (derived_entry_2 * tp.eta) + (derived_entry_3 * tp.etaTwo) - + (wire(p, WIRE.Q_O) * tp.etaThree); - } - - Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; - Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; - - Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) - - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); - - // Inverse calculated correctly relation - Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; - accumulatorNone = accumulatorNone * domainSep; - - // Inverse - Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; - - evals[4] = accumulatorNone; - evals[5] = accumulatorOne; - } - - function accumulateDeltaRangeRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - Fr minus_one = Fr.wrap(0) - Fr.wrap(1); - Fr minus_two = Fr.wrap(0) - Fr.wrap(2); - Fr minus_three = Fr.wrap(0) - Fr.wrap(3); - - // Compute wire differences - Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); - Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); - Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); - Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); - - // Contribution 6 - { - Fr acc = delta_1; - acc = acc * (delta_1 + minus_one); - acc = acc * (delta_1 + minus_two); - acc = acc * (delta_1 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[6] = acc; - } - - // Contribution 7 - { - Fr acc = delta_2; - acc = acc * (delta_2 + minus_one); - acc = acc * (delta_2 + minus_two); - acc = acc * (delta_2 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[7] = acc; - } - - // Contribution 8 - { - Fr acc = delta_3; - acc = acc * (delta_3 + minus_one); - acc = acc * (delta_3 + minus_two); - acc = acc * (delta_3 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[8] = acc; - } - - // Contribution 9 - { - Fr acc = delta_4; - acc = acc * (delta_4 + minus_one); - acc = acc * (delta_4 + minus_two); - acc = acc * (delta_4 + minus_three); - acc = acc * wire(p, WIRE.Q_RANGE); - acc = acc * domainSep; - evals[9] = acc; - } - } - - struct EllipticParams { - // Points - Fr x_1; - Fr y_1; - Fr x_2; - Fr y_2; - Fr y_3; - Fr x_3; - // push accumulators into memory - Fr x_double_identity; - } - - function accumulateEllipticRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal view { - EllipticParams memory ep; - ep.x_1 = wire(p, WIRE.W_R); - ep.y_1 = wire(p, WIRE.W_O); - - ep.x_2 = wire(p, WIRE.W_L_SHIFT); - ep.y_2 = wire(p, WIRE.W_4_SHIFT); - ep.y_3 = wire(p, WIRE.W_O_SHIFT); - ep.x_3 = wire(p, WIRE.W_R_SHIFT); - - Fr q_sign = wire(p, WIRE.Q_L); - Fr q_is_double = wire(p, WIRE.Q_M); - - // Contribution 10 point addition, x-coordinate check - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - Fr x_diff = (ep.x_2 - ep.x_1); - Fr y1_sqr = (ep.y_1 * ep.y_1); - { - // Move to top - Fr partialEval = domainSep; - - Fr y2_sqr = (ep.y_2 * ep.y_2); - Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; - Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); - x_add_identity = x_add_identity * x_diff * x_diff; - x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; - - evals[10] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (Fr.wrap(1) - q_is_double); - } - - // Contribution 11 point addition, x-coordinate check - // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 - { - Fr y1_plus_y3 = ep.y_1 + ep.y_3; - Fr y_diff = ep.y_2 * q_sign - ep.y_1; - Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; - evals[11] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (Fr.wrap(1) - q_is_double); - } - - // Contribution 10 point doubling, x-coordinate check - // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 - // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 - { - Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; - Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; - y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; - Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); - - // NOTE: pushed into memory (stack >:'( ) - ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; - - Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; - evals[10] = evals[10] + acc; - } - - // Contribution 11 point doubling, y-coordinate check - // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 - { - Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; - Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); - evals[11] = evals[11] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; - } - } - - // Constants for the auxiliary relation - Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); - Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); - Fr constant MINUS_ONE = Fr.wrap(P - 1); - - // Parameters used within the Auxiliary Relation - // A struct is used to work around stack too deep. This relation has alot of variables - struct AuxParams { - Fr limb_subproduct; - Fr non_native_field_gate_1; - Fr non_native_field_gate_2; - Fr non_native_field_gate_3; - Fr limb_accumulator_1; - Fr limb_accumulator_2; - Fr memory_record_check; - Fr partial_record_check; - Fr next_gate_access_type; - Fr record_delta; - Fr index_delta; - Fr adjacent_values_match_if_adjacent_indices_match; - Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; - Fr access_check; - Fr next_gate_access_type_is_boolean; - Fr ROM_consistency_check_identity; - Fr RAM_consistency_check_identity; - Fr timestamp_delta; - Fr RAM_timestamp_check_identity; - Fr memory_identity; - Fr index_is_monotonically_increasing; - Fr auxiliary_identity; - } - - function accumulateAuxillaryRelation( - Fr[NUMBER_OF_ENTITIES] memory p, - Transcript memory tp, - Fr[NUMBER_OF_SUBRELATIONS] memory evals, - Fr domainSep - ) internal pure { - AuxParams memory ap; - - /** - * Contribution 12 - * Non native field arithmetic gate 2 - * deg 4 - * - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - * - */ - ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); - ap.non_native_field_gate_2 = - (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; - ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); - - ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; - ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); - ap.non_native_field_gate_1 = ap.limb_subproduct; - ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); - ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); - - ap.non_native_field_gate_3 = ap.limb_subproduct; - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); - ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); - - Fr non_native_field_identity = - ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; - non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); - - // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm - // deg 2 - ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; - ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); - ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); - ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); - - // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm - // deg 2 - ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; - ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); - ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); - ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); - - Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; - limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 - - /** - * MEMORY - * - * A RAM memory record contains a tuple of the following fields: - * * i: `index` of memory cell being accessed - * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) - * * v: `value` of memory cell being accessed - * * a: `access` type of record. read: 0 = read, 1 = write - * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three - * - * A ROM memory record contains a tuple of the following fields: - * * i: `index` of memory cell being accessed - * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) - * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) - * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three - * - * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + - * selectors, depending on whether the gate is a RAM read/write or a ROM read - * - * | gate type | i | v2/t | v | a | r | - * | --------- | -- | ----- | -- | -- | -- | - * | ROM | w1 | w2 | w3 | -- | w4 | - * | RAM | w1 | w2 | w3 | qc | w4 | - * - * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on - * `w2` to fix its value) - * - * - */ - - /** - * Memory Record Check - * Partial degree: 1 - * Total degree: 4 - * - * A ROM/ROM access gate can be evaluated with the identity: - * - * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 - * - * For ROM gates, qc = 0 - */ - ap.memory_record_check = wire(p, WIRE.W_O) * tp.etaThree; - ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * tp.etaTwo); - ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * tp.eta); - ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); - ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 - ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); - - /** - * Contribution 13 & 14 - * ROM Consistency Check - * Partial degree: 1 - * Total degree: 4 - * - * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of - * records that are sorted. - * - * We apply the following checks for the sorted records: - * - * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 - * 2. index values for adjacent records are monotonically increasing - * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} - * - */ - ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); - ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); - - ap.index_is_monotonically_increasing = ap.index_delta * ap.index_delta - ap.index_delta; // deg 2 - - ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + Fr.wrap(1)) * ap.record_delta; // deg 2 - - evals[13] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) - * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 - evals[14] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) - * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 - - ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 - - /** - * Contributions 15,16,17 - * RAM Consistency Check - * - * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` - * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. - * This is validated by requiring `access` to be boolean - * - * For two adjacent entries in the sorted list if _both_ - * A) index values match - * B) adjacent access value is 0 (i.e. next gate is a READ) - * then - * C) both values must match. - * The gate boolean check is - * (A && B) => C === !(A && B) || C === !A || !B || C - * - * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized - * with a WRITE operation. - */ - Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 - ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 - - // TODO(https://github.com/AztecProtocol/barretenberg/issues/757): If we sorted in - // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta - // deg 1 or 4 - ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * tp.etaThree; - ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * tp.etaTwo); - ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * tp.eta); - ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; - - Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); - ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = ( - ap.index_delta * MINUS_ONE + Fr.wrap(1) - ) * value_delta * (ap.next_gate_access_type * MINUS_ONE + Fr.wrap(1)); // deg 3 or 6 - - // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the - // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't - // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access - // type is correct, to cover this edge case - // deg 2 or 4 - ap.next_gate_access_type_is_boolean = - ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; - - // Putting it all together... - evals[15] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation - * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 5 or 8 - evals[16] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 - evals[17] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 6 - - ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9 - - /** - * RAM Timestamp Consistency Check - * - * | w1 | w2 | w3 | w4 | - * | index | timestamp | timestamp_check | -- | - * - * Let delta_index = index_{i + 1} - index_{i} - * - * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i - * Else timestamp_check = 0 - */ - ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); - ap.RAM_timestamp_check_identity = - (ap.index_delta * MINUS_ONE + Fr.wrap(1)) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 - - /** - * Complete Contribution 12 - * The complete RAM/ROM memory identity - * Partial degree: - */ - ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 - ap.memory_identity = - ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 - ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 - ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 - - // (deg 3 or 9) + (deg 4) + (deg 3) - ap.auxiliary_identity = ap.memory_identity + non_native_field_identity + limb_accumulator_identity; - ap.auxiliary_identity = ap.auxiliary_identity * (wire(p, WIRE.Q_AUX) * domainSep); // deg 4 or 10 - evals[12] = ap.auxiliary_identity; - } - - function scaleAndBatchSubrelations( - Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, - Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges - ) internal view returns (Fr accumulator) { - accumulator = accumulator + evaluations[0]; - - for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { - accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; - } - } - function verifyZeroMorph(Honk.Proof memory proof, Honk.VerificationKey memory vk, Transcript memory tp) internal view @@ -1183,12 +277,12 @@ contract EcdsaHonkVerifier is IVerifier { // f commitments are accumulated at (zm_x * r) cp.rho_pow = Fr.wrap(1); - for (uint256 i = 1; i < 34; ++i) { + for (uint256 i = 1; i <= NUMBER_UNSHIFTED; ++i) { scalars[i] = tp.zmX * cp.rho_pow; cp.rho_pow = cp.rho_pow * tp.rho; } // g commitments are accumulated at r - for (uint256 i = 34; i < 43; ++i) { + for (uint256 i = NUMBER_UNSHIFTED + 1; i <= NUMBER_OF_ENTITIES; ++i) { scalars[i] = cp.rho_pow; cp.rho_pow = cp.rho_pow * tp.rho; } @@ -1205,41 +299,43 @@ contract EcdsaHonkVerifier is IVerifier { commitments[9] = vk.qElliptic; commitments[10] = vk.qAux; commitments[11] = vk.qLookup; - commitments[12] = vk.s1; - commitments[13] = vk.s2; - commitments[14] = vk.s3; - commitments[15] = vk.s4; - commitments[16] = vk.id1; - commitments[17] = vk.id2; - commitments[18] = vk.id3; - commitments[19] = vk.id4; - commitments[20] = vk.t1; - commitments[21] = vk.t2; - commitments[22] = vk.t3; - commitments[23] = vk.t4; - commitments[24] = vk.lagrangeFirst; - commitments[25] = vk.lagrangeLast; + commitments[12] = vk.qPoseidon2External; + commitments[13] = vk.qPoseidon2Internal; + commitments[14] = vk.s1; + commitments[15] = vk.s2; + commitments[16] = vk.s3; + commitments[17] = vk.s4; + commitments[18] = vk.id1; + commitments[19] = vk.id2; + commitments[20] = vk.id3; + commitments[21] = vk.id4; + commitments[22] = vk.t1; + commitments[23] = vk.t2; + commitments[24] = vk.t3; + commitments[25] = vk.t4; + commitments[26] = vk.lagrangeFirst; + commitments[27] = vk.lagrangeLast; // Accumulate proof points - commitments[26] = convertProofPoint(proof.w1); - commitments[27] = convertProofPoint(proof.w2); - commitments[28] = convertProofPoint(proof.w3); - commitments[29] = convertProofPoint(proof.w4); - commitments[30] = convertProofPoint(proof.zPerm); - commitments[31] = convertProofPoint(proof.lookupInverses); - commitments[32] = convertProofPoint(proof.lookupReadCounts); - commitments[33] = convertProofPoint(proof.lookupReadTags); + commitments[28] = convertProofPoint(proof.w1); + commitments[29] = convertProofPoint(proof.w2); + commitments[30] = convertProofPoint(proof.w3); + commitments[31] = convertProofPoint(proof.w4); + commitments[32] = convertProofPoint(proof.zPerm); + commitments[33] = convertProofPoint(proof.lookupInverses); + commitments[34] = convertProofPoint(proof.lookupReadCounts); + commitments[35] = convertProofPoint(proof.lookupReadTags); // to be Shifted - commitments[34] = vk.t1; - commitments[35] = vk.t2; - commitments[36] = vk.t3; - commitments[37] = vk.t4; - commitments[38] = convertProofPoint(proof.w1); - commitments[39] = convertProofPoint(proof.w2); - commitments[40] = convertProofPoint(proof.w3); - commitments[41] = convertProofPoint(proof.w4); - commitments[42] = convertProofPoint(proof.zPerm); + commitments[36] = vk.t1; + commitments[37] = vk.t2; + commitments[38] = vk.t3; + commitments[39] = vk.t4; + commitments[40] = convertProofPoint(proof.w1); + commitments[41] = convertProofPoint(proof.w2); + commitments[42] = convertProofPoint(proof.w3); + commitments[43] = convertProofPoint(proof.w4); + commitments[44] = convertProofPoint(proof.zPerm); // Add scalar contributions // Add contributions: scalar * [q_k], k = 0,...,log_N, where @@ -1264,8 +360,8 @@ contract EcdsaHonkVerifier is IVerifier { cp.x_pow_2kp1 = cp.x_pow_2kp1 * cp.x_pow_2kp1; } - scalars[43 + k] = scalar; - commitments[43 + k] = convertProofPoint(proof.zmCqs[k]); + scalars[NUMBER_OF_ENTITIES + 1 + k] = scalar; + commitments[NUMBER_OF_ENTITIES + 1 + k] = convertProofPoint(proof.zmCqs[k]); } return batchMul2(commitments, scalars); @@ -1284,7 +380,7 @@ contract EcdsaHonkVerifier is IVerifier { let free := mload(0x40) // Write the original into the accumulator - // Load into memory for ecMUL, leave offset for eccAdd result + // Load into memory forecMUL, leave offset foreccAdd result // base is an array of pointers, so we have to dereference them mstore(add(free, 0x40), mload(mload(base))) mstore(add(free, 0x60), mload(add(0x20, mload(base)))) @@ -1324,7 +420,7 @@ contract EcdsaHonkVerifier is IVerifier { let free := mload(0x40) // Write the original into the accumulator - // Load into memory for ecMUL, leave offset for eccAdd result + // Load into memory forecMUL, leave offset foreccAdd result // base is an array of pointers, so we have to dereference them mstore(add(free, 0x40), mload(mload(base))) mstore(add(free, 0x60), mload(add(0x20, mload(base)))) diff --git a/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol b/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol index 1b9ba31c154..2402e0a4069 100644 --- a/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol +++ b/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol @@ -58,21 +58,29 @@ library Add2HonkVerificationKey { x: uint256(0x19e2d786ebad24caf1bef735441e58525a2f9b5807b2102f295c58cde00f5c97), y: uint256(0x085713ce7bac807a084a66904ebc6e695840e8cf405a6fd0c325f8bfcf7c2dd8) }), + qPoseidon2External: Honk.G1Point({ + x: uint256(0x0ca0bc4b1cd9eadbbf49eae56a99a4502ef13d965226a634d0981555e4a4da56), + y: uint256(0x1a8a818e6c61f68cefa329f2fabc95c80ad56a538d852f75eda858ed1a616c74) + }), + qPoseidon2Internal: Honk.G1Point({ + x: uint256(0x09dfd2992ac1708f0dd1d28c2ad910d9cf21a1510948580f406bc9416113d620), + y: uint256(0x205f76eebda12f565c98c775c4e4f3534b5dcc29e57eed899b1a1a880534dcb9) + }), s1: Honk.G1Point({ - x: uint256(0x039e4b13c22e227df79cafc6a8a9e8cc6217791d738ccad75c88d4a150cf9324), - y: uint256(0x16b832f3a75a8dffdb969bb79918867eaff198957c687d20ebc726dcbd61f9e1) + x: uint256(0x19a07402ffcc103c3d8fbfbc7e9a660147d7380e65c34f64b75701b8d4868c11), + y: uint256(0x0b7ab8c749a4af75d6100dba9246d7f993748b326d23791a595e21a17653fe30) }), s2: Honk.G1Point({ - x: uint256(0x165d5d53619ae0694e61c26302abfe39bc20646fd04210519520980f3ffb91d2), - y: uint256(0x10f0c4a0b216e66fe2f88ae617b54347fa41fce598ec801dd289394890f3b66b) + x: uint256(0x027234cb39eacbf2ebe98907cf433e429a37933e429d4f24df14274b5c4d2549), + y: uint256(0x2c1ea0996e3fd6cfabcfc6bbd4c86c65fb19c3dda2ded5c4f973af397e8e5c8b) }), s3: Honk.G1Point({ - x: uint256(0x0afca124a27006abfd194b1ad23b404f2112d11fe95ec69cc705f02258adc913), - y: uint256(0x2c1acafafadacc271d5297ab45bc79a5a3c87916578d8309493c2e2507bbe508) + x: uint256(0x243daee8a40861aba1ef660929ee9e874e52cd8e8d75f8c0245852369a731491), + y: uint256(0x0a20f23c0697fb0698478f7a861dde5e18bf5aa34f4731178e74f7460df49a88) }), s4: Honk.G1Point({ - x: uint256(0x0f7cf2c8c0cd0fe37630e8f79ba6dffd59c0fd1f2f6ae5789efab86d4c1c0007), - y: uint256(0x25bde264a751e99cf36bb64034710e55b3b1e02234c75a35683c91274d445ed8) + x: uint256(0x18b8202abb615440b5544d88092245911d2b5ff3b5a4a80bb15dbabafdfb56a7), + y: uint256(0x096a6685f36b1ca09a62820ae3be7538128093440fa943ea7412617a6d927916) }), t1: Honk.G1Point({ x: uint256(0x2e0cddbc5712d79b59cb3b41ebbcdd494997477ab161763e46601d95844837ef), diff --git a/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol b/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol index 49f2ae375c0..0eaeba194f1 100644 --- a/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol +++ b/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol @@ -58,21 +58,29 @@ library BlakeHonkVerificationKey { x: uint256(0x1375bbfbf5ed31b38460f46a43ac14e2cda93a3bc5cfd6e8a93cca356694a346), y: uint256(0x204c5173892c19a97a04b5f8419898063df5136489809ddb9f7eabb58d6858ab) }), + qPoseidon2External: Honk.G1Point({ + x: uint256(0x1fa8529236d7eacdab8dcd8169af30d334be103357577353e9ef08dfda841785), + y: uint256(0x055251b013746385e921b4620e55ef4f08b4d8afc4dbca7e6c3ca0f1b52c5a2b) + }), + qPoseidon2Internal: Honk.G1Point({ + x: uint256(0x1515283648ab8622ac6447f1fcf201a598d8df325279bfac9a6564924df97ee5), + y: uint256(0x0335bb595984ad38686009bca08f5f420e3b4cf888fad5af4a99eca08190a315) + }), s1: Honk.G1Point({ - x: uint256(0x07205fa20c0a8ff2aab958f4dfc4fa14449aad08f66de2341412a70ca6cb972b), - y: uint256(0x1341c9e5d1300703ae7ab1689c2d83a843ec898e5120a2b52b4323e2acf94f30) + x: uint256(0x26cec5ff3eb1b803c52fa1fefaac7a2be5cd13c1a1cc20bb9f22049c7f8597d2), + y: uint256(0x07e80e74eb0e06d7c0c9a3fbbdea4e86e5934faa8142625f175320778bcba65f) }), s2: Honk.G1Point({ - x: uint256(0x09821cc06874047f1204cf5c13d5d24951757e727368690715de0e8160f50eeb), - y: uint256(0x01675621d2a4202874b596d732f983f06524dbcc855a08dadd9925e29c02c7e3) + x: uint256(0x140b2faaf30cb5fc528621f4a395943e7fab8198dc734ac13253dd249682dd2a), + y: uint256(0x12709c4a13428f4704d284c90a81cc83280680185ae6298187e86debcd3e00f7) }), s3: Honk.G1Point({ - x: uint256(0x2567d6126bd4dfa15eecbda777e9c86566fc5817b87bdd479e558919cd5aa96b), - y: uint256(0x2ac31be3d7a2f45625b98c022106a076c0c4730299c18d48c7739d423e53bd94) + x: uint256(0x0aca5621e9f49279969497b3da0eb8a74c68c3513f4cf98e8b1d6f88567557a8), + y: uint256(0x2664811311f75057a16267bc0479eaeea2424156417cc4d3f8bd286fac9aa5d2) }), s4: Honk.G1Point({ - x: uint256(0x15d68f126e0adc08580957fad3db16973c5c7f47a64d04646204c2b14ec14482), - y: uint256(0x3048e354794e4dbcbb670dc137409427a954eb899bdba8bbaeec5ba7f3a79170) + x: uint256(0x04417c606a41393e73113ec3f834883dbeb302889199b888c0f5ea58a008ff98), + y: uint256(0x0865670de7962d29b6a9012f28ea52113c4e2b55d7de44e829edec87dba1d5c2) }), t1: Honk.G1Point({ x: uint256(0x1ec1b607634e31421b5047dc99d7674d6505fed978df0f42a3504f9771a8a7fa), diff --git a/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol b/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol index 1ef78325263..b2d9abdf2a2 100644 --- a/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol +++ b/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol @@ -58,21 +58,29 @@ library EcdsaHonkVerificationKey { x: uint256(0x13a5f6d8f4de0f66dc7ea0d75efa7ae6632e6448c13bbbe5358412f7a36518d6), y: uint256(0x142fd8f3223785fbd36b380c6065215d16b821b3df4d86d5464f1bfff2a29544) }), + qPoseidon2External: Honk.G1Point({ + x: uint256(0x02c909437bb59751312ce2208a2b367d3c9eaa8721d7671306c41ebd9843b3ba), + y: uint256(0x1db8a23e0231ac4b008ccdb6f21aa37c59349a77b51d894217596f0ef543120c) + }), + qPoseidon2Internal: Honk.G1Point({ + x: uint256(0x19d898bac51355e0822e2aa6e6630494e47ea2476a0c4c15b6f03ce441f6c6d0), + y: uint256(0x2add808f3d5b3c608ce5937fcd3c9c968ba56dbe5855e2f6d3e4bdd9d118d19b) + }), s1: Honk.G1Point({ - x: uint256(0x12f95fba378f68a39b900e458349c0f778dca65e2627bb1c5d6284c2b1260ef1), - y: uint256(0x15965dc624e9a40d1ffe0343f8fd4c2afdb6ac86e0f487ab8c4fe2a85d1036f4) + x: uint256(0x0dd1eea7735fc4052df5a19e4859c59e50e3ab9cb3cc2accbd42ef8a1104449b), + y: uint256(0x1541af79ad21fe21642a50d97899451c868b6d5d608431e5de6b0a730abe130d) }), s2: Honk.G1Point({ - x: uint256(0x1c260f913ab6417444cf9512dc273201aa34946e41d75fa81c3626c81fe716ff), - y: uint256(0x176e7818b3dfff8b2744f5b5d2c0a2ebdafcd9286c795270092dfbe25a9c08af) + x: uint256(0x21d9072c3474c1cfe1c2d96c098c4d9af4bb5d222944aa6470063f4a8b9b9770), + y: uint256(0x137ad8c018449f48311b5394ac91a6b2f5c5e40c676216a299a3d501d69b1f7d) }), s3: Honk.G1Point({ - x: uint256(0x16945d3d1dc53de6aeaff189e40c72c9de0ac1dd796345064c0af5e092e8e3f1), - y: uint256(0x21f48c50caca803009a007bc66421e7135ece814e02767a43cb5a7ec60b4e7d8) + x: uint256(0x2c2fe61ccbf18af13d41950ef58f3a2a64d355657a4dfba8e9917e618ea8add4), + y: uint256(0x2e7edf4dae50db17925e431d3198a39cb4bdc6f4e6e7d8d6163c972f4750a606) }), s4: Honk.G1Point({ - x: uint256(0x187a3c8a8fa68d820cdcbdda2aec2fd6af5495bce3ec51a86a9043ed828cac12), - y: uint256(0x08d15b3ae7be0b34eac0495b771c58ec10b386e4e614301b4b00e2b0e360f8e0) + x: uint256(0x1825a30f42c7508e2ee2158d374dc626cf4149b745ba55d533181f418ac605aa), + y: uint256(0x15d9b33a9612c0c8a55a75a827c0230656054765c7b37ba77a798b71a4766d1b) }), t1: Honk.G1Point({ x: uint256(0x1ddc9ef86584375e5998d9f6fc16a4e646dc315ab86b477abc2f18a723dc24f6), diff --git a/barretenberg/sol/src/honk/utils.sol b/barretenberg/sol/src/honk/utils.sol index 340204c20bc..15d5e9b7b67 100644 --- a/barretenberg/sol/src/honk/utils.sol +++ b/barretenberg/sol/src/honk/utils.sol @@ -1,6 +1,10 @@ -import {Honk, P, Q} from "./HonkTypes.sol"; +pragma solidity >=0.8.21; + +import {Honk} from "./HonkTypes.sol"; import {Fr, FrLib} from "./Fr.sol"; +uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q + import "forge-std/console.sol"; import "forge-std/console2.sol"; diff --git a/barretenberg/sol/src/ultra/keys/Add2UltraVerificationKey.sol b/barretenberg/sol/src/ultra/keys/Add2UltraVerificationKey.sol index a0d4ffe2030..341b831b05a 100644 --- a/barretenberg/sol/src/ultra/keys/Add2UltraVerificationKey.sol +++ b/barretenberg/sol/src/ultra/keys/Add2UltraVerificationKey.sol @@ -1,11 +1,11 @@ -// Verification Key Hash: cb63e1832e42d0a3dc85a0e3bbd22598bbb6cd6fcdb99e9c33f3907e88e3cb89 +// Verification Key Hash: 4199008b0f295433fcc5b10612c7b9a9d87fbd4a221275c2119e7c2060905534 // SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec pragma solidity >=0.8.4; library Add2UltraVerificationKey { function verificationKeyHash() internal pure returns (bytes32) { - return 0xcb63e1832e42d0a3dc85a0e3bbd22598bbb6cd6fcdb99e9c33f3907e88e3cb89; + return 0x4199008b0f295433fcc5b10612c7b9a9d87fbd4a221275c2119e7c2060905534; } function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { diff --git a/barretenberg/sol/src/ultra/keys/BlakeUltraVerificationKey.sol b/barretenberg/sol/src/ultra/keys/BlakeUltraVerificationKey.sol index 9fff4b5d5bf..27de321eb3d 100644 --- a/barretenberg/sol/src/ultra/keys/BlakeUltraVerificationKey.sol +++ b/barretenberg/sol/src/ultra/keys/BlakeUltraVerificationKey.sol @@ -1,11 +1,11 @@ -// Verification Key Hash: 5a6117dce0e70786bb6b9b3d1c4fd733404425849005cd2242fb3b12e431a162 +// Verification Key Hash: f1610f1094b31fc37136369383140118871a3bf69a190023d73dce30a3e5ba2e // SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec pragma solidity >=0.8.4; library BlakeUltraVerificationKey { function verificationKeyHash() internal pure returns (bytes32) { - return 0x5a6117dce0e70786bb6b9b3d1c4fd733404425849005cd2242fb3b12e431a162; + return 0xf1610f1094b31fc37136369383140118871a3bf69a190023d73dce30a3e5ba2e; } function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { diff --git a/barretenberg/sol/src/ultra/keys/EcdsaUltraVerificationKey.sol b/barretenberg/sol/src/ultra/keys/EcdsaUltraVerificationKey.sol index 3d6bc213f06..63a0b71a890 100644 --- a/barretenberg/sol/src/ultra/keys/EcdsaUltraVerificationKey.sol +++ b/barretenberg/sol/src/ultra/keys/EcdsaUltraVerificationKey.sol @@ -1,11 +1,11 @@ -// Verification Key Hash: 39dd0e98b3f192bce78868c74aa2b07397650909b73e3589a5bfbfbecba53dfc +// Verification Key Hash: c1102f0000ae4bf7f5b38f96c80e03284a3ec4bada1f0682ddde94c8ba688c58 // SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec pragma solidity >=0.8.4; library EcdsaUltraVerificationKey { function verificationKeyHash() internal pure returns (bytes32) { - return 0x39dd0e98b3f192bce78868c74aa2b07397650909b73e3589a5bfbfbecba53dfc; + return 0xc1102f0000ae4bf7f5b38f96c80e03284a3ec4bada1f0682ddde94c8ba688c58; } function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { diff --git a/barretenberg/sol/test/base/TestBase.sol b/barretenberg/sol/test/base/TestBase.sol index ecf458e28a3..9b111bfd7bd 100644 --- a/barretenberg/sol/test/base/TestBase.sol +++ b/barretenberg/sol/test/base/TestBase.sol @@ -22,6 +22,7 @@ contract TestBase is Test { let rLoc := add(rawBytes, 0x24) let end := add(rLoc, length) + // TODO: Can be updated with new evm mcpy opcode for {} lt(rLoc, end) { wLoc := add(wLoc, 0x20) rLoc := add(rLoc, 0x20) diff --git a/barretenberg/ts/CHANGELOG.md b/barretenberg/ts/CHANGELOG.md index 5775fae2ac0..1963704d06e 100644 --- a/barretenberg/ts/CHANGELOG.md +++ b/barretenberg/ts/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [0.54.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.53.0...barretenberg.js-v0.54.0) (2024-09-10) + + +### Miscellaneous + +* **barretenberg.js:** Synchronize aztec-packages versions + +## [0.53.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.52.0...barretenberg.js-v0.53.0) (2024-09-09) + + +### Bug Fixes + +* HonkRecursion serde for cpp bindings ([#8387](https://github.com/AztecProtocol/aztec-packages/issues/8387)) ([6162179](https://github.com/AztecProtocol/aztec-packages/commit/6162179ffc9b04213ef600e1733d2ac696c1dbe6)) + ## [0.52.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.51.1...barretenberg.js-v0.52.0) (2024-09-01) diff --git a/barretenberg/ts/package.json b/barretenberg/ts/package.json index e99d405e0f5..28490f7cf5d 100644 --- a/barretenberg/ts/package.json +++ b/barretenberg/ts/package.json @@ -1,7 +1,7 @@ { "name": "@aztec/bb.js", "packageManager": "yarn@1.22.22", - "version": "0.52.0", + "version": "0.54.0", "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/ts", "license": "MIT", "type": "module", diff --git a/bb-pilcom/bb-pil-backend/templates/circuit_builder.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/circuit_builder.cpp.hbs index 4ac476e2c67..13cb0632d5d 100644 --- a/bb-pilcom/bb-pil-backend/templates/circuit_builder.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/circuit_builder.cpp.hbs @@ -18,13 +18,20 @@ namespace bb { ProverPolynomials polys; // Allocate mem for each column - for (auto& poly : polys.get_all()) { - poly = Polynomial(num_rows); + + for (auto& poly : polys.get_to_be_shifted()) { + poly = Polynomial::shiftable(num_rows); + } + // catch-all with fully formed polynomials + for (auto& poly : polys.get_unshifted()) { + if (poly.is_empty()) { + poly = Polynomial{ num_rows }; + } } for (size_t i = 0; i < rows.size(); i++) { {{#each all_cols_without_inverses as |poly|}} - polys.{{poly}}[i] = rows[i].{{poly}}; + polys.{{poly}}.set_if_valid_index(i, rows[i].{{poly}}); {{/each}} } @@ -121,5 +128,5 @@ bool {{name}}CircuitBuilder::check_circuit() const { return errors.empty(); } - + } // namespace bb \ No newline at end of file diff --git a/bb-pilcom/bb-pil-backend/templates/flavor.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/flavor.cpp.hbs index f4ca977fe54..6d06471851a 100644 --- a/bb-pilcom/bb-pil-backend/templates/flavor.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/flavor.cpp.hbs @@ -46,6 +46,10 @@ namespace bb { {{/each}} }; +// Note: current de-/serialization routines are not including the padded zero univariates which are added as part of +// current sumcheck implementation. Namely, this algorithm is padding to reach CONST_PROOF_SIZE_LOG_N sumcheck rounds. +// Similarly, zeromorph implementation performs same padding over some commitments (zm_cq_comms). +// In code below, the loops are of size log(circuit_size) instead of CONST_PROOF_SIZE_LOG_N. void {{name}}Flavor::Transcript::deserialize_full_transcript() { size_t num_frs_read = 0; circuit_size = deserialize_from_buffer(proof_data, num_frs_read); @@ -68,6 +72,7 @@ void {{name}}Flavor::Transcript::deserialize_full_transcript() { zm_pi_comm = deserialize_from_buffer(proof_data, num_frs_read); } +// See note above AvmFlavor::Transcript::deserialize_full_transcript() void {{name}}Flavor::Transcript::serialize_full_transcript() { size_t old_proof_length = proof_data.size(); Transcript::proof_data.clear(); @@ -119,4 +124,20 @@ AvmFlavor::ProvingKey::ProvingKey(const size_t circuit_size, const size_t num_pu } }; +/** + * @brief Serialize verification key to field elements + * + * @return std::vector + */ +std::vector AvmFlavor::VerificationKey::to_field_elements() const +{ + std::vector elements = { FF(circuit_size), FF(num_public_inputs) }; + + for (auto const& comm : get_all()) { + std::vector comm_as_fields = field_conversion::convert_to_bn254_frs(comm); + elements.insert(elements.end(), comm_as_fields.begin(), comm_as_fields.end()); + } + return elements; +} + } // namespace bb \ No newline at end of file diff --git a/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs index 3aafbf028d5..0a9830d51c5 100644 --- a/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs @@ -195,10 +195,12 @@ class {{name}}Flavor { class VerificationKey : public VerificationKey_, VerifierCommitmentKey> { public: + using FF = VerificationKey_::FF; + VerificationKey() = default; VerificationKey(const std::shared_ptr& proving_key) - : VerificationKey_(proving_key->circuit_size, proving_key->num_public_inputs) + : VerificationKey_(proving_key->circuit_size, static_cast(proving_key->num_public_inputs)) { for (auto [polynomial, commitment] : zip_view(proving_key->get_precomputed_polynomials(), this->get_all())) { @@ -217,6 +219,8 @@ class {{name}}Flavor { } pcs_verification_key = std::make_shared(); } + + std::vector to_field_elements() const; }; {{!-- Used by sumcheck --}} diff --git a/boxes/Earthfile b/boxes/Earthfile index 0ceeb51ce4d..3c349f8aa49 100644 --- a/boxes/Earthfile +++ b/boxes/Earthfile @@ -50,6 +50,14 @@ boxes: RUN yarn install-browsers ENTRYPOINT ["/bin/sh", "-c"] +npx: + FROM ../build-images/+base-slim-node + COPY --dir +build/usr/src /usr + WORKDIR /usr/src/boxes + + RUN yarn + RUN yarn test:ci + BOX_TEST_LOCAL: FUNCTION ARG box diff --git a/boxes/README.md b/boxes/README.md index f75bbb5c08a..4510131c223 100644 --- a/boxes/README.md +++ b/boxes/README.md @@ -1,8 +1,10 @@ # Aztec-App Aztec-App is a set of tools to ease development on Aztec. It consists of two main components: + 1. `npx` script 2. boxes (starter kits) + ## npx script NPX is a tool bundled with `npm` and other package managers. It allows you to run a binary from a cache without installing it globally. @@ -13,9 +15,9 @@ To ease the development process, Aztec has developed this binary. To run it, ins npx aztec-app ``` -This will prompt you with some options to clone `Aztec Boxes` and install the sandbox. As the `npx` script evolves, other commands will be added or removed. You can run it with the `-h` flag to know what other commands and flags you can pass to it. +This will prompt you with some options to clone `Aztec Boxes`. As the `npx` script evolves, other commands will be added or removed. You can run it with the `-h` flag to know what other commands and flags you can pass to it. -> [!NOTE] +> [!NOTE] > As a tool that doesn't (yet) have automated testing, it versioning and release process is decoupled from `aztec`, and its deployment is entirely manual by running `yarn npm publish --access public`. ## Aztec Boxes @@ -26,7 +28,7 @@ Aztec Boxes are the one-stop-shop for developing on Aztec. They often include a - Frontend boilerplates - General tests -Boxes include the sandbox installation script and its start command. By choosing the appropriate box, you can get started working on Aztec in a minimal amount of time. +By choosing the appropriate box, you can get started working on Aztec in a minimal amount of time. ## Contributing @@ -37,9 +39,6 @@ Most of the logic is in the `bin.js` file, where `commander` commands stuff. The - Prompts the user for options and commands - Inits some global variables such as a logger, a getter for the github repositories, the latest stable versions and tags, etc - Prompts the user to choose the project and clone it. It then rewrites the `Nargo.toml` and `package.json` files to point to the repos instead of the local dependencies. -- Queries the local docker daemon for any existing sandbox images, prompting the user to install or update it if needed -- Asks the user if they want to run the sandbox right away - ## Templates diff --git a/boxes/bin.js b/boxes/bin.js index cd160479d05..858c1142fbb 100755 --- a/boxes/bin.js +++ b/boxes/bin.js @@ -2,18 +2,16 @@ import { Command } from "commander"; const program = new Command(); import { chooseProject } from "./scripts/steps/chooseBox.js"; -import { sandboxInstallOrUpdate } from "./scripts/steps/sandbox/install.js"; import axios from "axios"; import pino from "pino"; import pretty from "pino-pretty"; import ora from "ora"; import { AZTEC_REPO } from "./scripts/config.js"; -import { sandboxRunStep } from "./scripts/steps/sandbox/run.js"; import { init } from "./scripts/init.js"; const getLatestStable = async () => { const { data } = await axios.get( - `https://api.github.com/repos/AztecProtocol/aztec-packages/releases`, + `https://api.github.com/repos/AztecProtocol/aztec-packages/releases` ); return data[0].tag_name.split("-v")[1]; }; @@ -45,7 +43,7 @@ program }, level: debug ? "debug" : "info", }, - prettyStream, + prettyStream ); global.debug = (msg) => logger.debug(msg); @@ -100,17 +98,13 @@ program program .command("new", { isDefault: true }) .description("An Aztec project with a built-in development network") - .option( - "-s, --skip-sandbox", - "skip sandbox installation and run after cloning", - ) .option( "-t, --project-type ", - "the type of the project to clone ('app' or 'contract')", + "the type of the project to clone ('app' or 'contract')" ) .option( "-n, --project-name ", - "the name of the project to clone", + "the name of the project to clone" ) .action(async (options) => { // this is some bad code, but it's def fun @@ -121,16 +115,10 @@ program throw Error("You must define both the project type and the project name"); } - const { projectType, projectName, skipSandbox } = options; + const { projectType, projectName } = options; // // STEP 1: Choose the boilerplate await chooseProject({ projectType, projectName }); - - if (skipSandbox) return; - // // STEP 2: Install the Sandbox - await sandboxInstallOrUpdate({ skipQuestion: skipSandbox }); - // STEP 3: Running the Sandbox - await sandboxRunStep({ skipQuestion: skipSandbox }); }); program.parse(); diff --git a/boxes/bin.test.js b/boxes/bin.test.js new file mode 100644 index 00000000000..23b5720c17d --- /dev/null +++ b/boxes/bin.test.js @@ -0,0 +1,91 @@ +import { parse } from "@iarna/toml"; +import axios from "axios"; +import { execSync } from "child_process"; +import fs from "fs/promises"; +import path from "path"; +import { describe, test, expect, beforeAll } from "vitest"; + +const getLatestStable = async () => { + try { + const { data } = await axios.get( + `https://api.github.com/repos/AztecProtocol/aztec-packages/releases`, + ); + return data[0].tag_name.split("-v")[1]; + } catch (error) { + console.error("Error fetching latest stable version:", error); + return; + } +}; + +const version = await getLatestStable(); +const tag = version.match(/^\d+\.\d+\.\d+$/) + ? `aztec-packages-v${version}` + : version; + +describe("Token contract", () => { + beforeAll(() => { + try { + execSync("npx . new -d -t contract -n token_contract", { + stdio: "inherit", + }); + } catch (error) { + console.error("Error executing command:", error); + } + }); + + test("Paths were updated correctly", async () => { + const replaces = []; + const findAndReplace = async (dir, prefix) => { + const files = await fs.readdir(dir, { + withFileTypes: true, + }); + files.forEach(async (file) => { + const filePath = path.join(dir, file.name); + if (file.isDirectory()) { + findAndReplace(filePath, prefix); // Recursively search subdirectories + } else if (file.name === "Nargo.toml") { + replaces.push( + new Promise(async (resolve, reject) => { + let content = parse(await fs.readFile(filePath, "utf8")); + if (!content.dependencies) return; + resolve( + Object.keys(content.dependencies) + .filter((dep) => dep.match("@aztec")) + .every( + (dep) => + content.dependencies[dep] === + JSON.stringify({ + git: `https://github.com/${AZTEC_REPO}/`, + tag, + directory: `${prefix}${directory}`, + }), + ), + ); + }), + ); + } else if (file.name === "package.json") { + replaces.push( + new Promise(async (resolve, reject) => { + let content = JSON.parse(await fs.readFile(filePath, "utf8")); + if (!content.dependencies) return; + resolve( + Object.keys(content.dependencies) + .filter((deps) => deps.match("@aztec")) + // "master" actually means "latest" for the npm release + .every( + (dep) => + content.dependencies[dep] === + `${version === "master" ? "latest" : `^${version}`}`, + ), + ); + }), + ); + } + }); + }; + + await findAndReplace(path.resolve("./token_contract"), ""); + const res = await Promise.all(replaces); + expect(res).toEqual([true, true]); + }); +}); diff --git a/boxes/boxes/react/README.md b/boxes/boxes/react/README.md index 03f03cde8c0..03d756b6ccb 100644 --- a/boxes/boxes/react/README.md +++ b/boxes/boxes/react/README.md @@ -22,13 +22,7 @@ The above method just uses the `npx` command, AKA "unboxing the box". This is a Just open a terminal and write: ```bash -npx create-aztec-app -``` - -It should ask you some questions about your project, install and run the Sandbox (local developer network). You can also start, stop, update, and do other things on the sandbox through this script. Just run: - -```bash -npx create-aztec-app sandbox --help +npx aztec-app ``` ## More information diff --git a/boxes/boxes/react/package.json b/boxes/boxes/react/package.json index 8e574163eb5..5cc5308529b 100644 --- a/boxes/boxes/react/package.json +++ b/boxes/boxes/react/package.json @@ -47,13 +47,14 @@ "yup": "^1.2.0" }, "devDependencies": { - "@playwright/test": "1.42.0", + "@playwright/test": "1.46.1", "@types/jest": "^29.5.0", "@types/node": "^20.5.9", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", + "assert": "^2.1.0", "autoprefixer": "^10.4.15", "copy-webpack-plugin": "^11.0.0", "css-loader": "^6.8.1", diff --git a/boxes/boxes/react/webpack.config.js b/boxes/boxes/react/webpack.config.js index 4db17529911..8573528ab47 100644 --- a/boxes/boxes/react/webpack.config.js +++ b/boxes/boxes/react/webpack.config.js @@ -37,6 +37,7 @@ export default (_, argv) => ({ resolve: { extensions: ['.tsx', '.ts', '.js'], fallback: { + assert: require.resolve('assert/'), crypto: false, os: false, fs: false, diff --git a/boxes/boxes/vanilla/README.md b/boxes/boxes/vanilla/README.md index 8190eb5d4cd..3239a7528a1 100644 --- a/boxes/boxes/vanilla/README.md +++ b/boxes/boxes/vanilla/README.md @@ -2,7 +2,6 @@ This box is a one-stop-shop for Aztec that will deploy a minimal barebones HTML+JS page. You can use it as a boilerplate to start developing your own Aztec app in seconds! - ## Getting Started The easiest way to start is with a Github Codespaces, which has a generous free tier. Just click on this button: @@ -23,13 +22,7 @@ The above method just uses the `npx` command, AKA "unboxing the box". This is a Just open a terminal and write: ```bash -npx create-aztec-app -``` - -It should ask you some questions about your project, install and run the Sandbox (local developer network). You can also start, stop, update, and do other things on the sandbox through this script. Just run: - -```bash -npx create-aztec-app sandbox --help +npx aztec-app ``` ## More information diff --git a/boxes/boxes/vanilla/package.json b/boxes/boxes/vanilla/package.json index 045d0e976fa..9f99d42e0ee 100644 --- a/boxes/boxes/vanilla/package.json +++ b/boxes/boxes/vanilla/package.json @@ -22,8 +22,9 @@ "@aztec/builder": "latest" }, "devDependencies": { - "@playwright/test": "1.42.0", + "@playwright/test": "1.46.1", "@types/node": "^20.11.17", + "assert": "^2.1.0", "copy-webpack-plugin": "^11.0.0", "html-webpack-plugin": "^5.6.0", "stream-browserify": "^3.0.0", diff --git a/boxes/boxes/vanilla/webpack.config.js b/boxes/boxes/vanilla/webpack.config.js index 6fe89595fe0..caea8b8ecd4 100644 --- a/boxes/boxes/vanilla/webpack.config.js +++ b/boxes/boxes/vanilla/webpack.config.js @@ -33,6 +33,7 @@ export default (_, argv) => ({ resolve: { extensions: ['.tsx', '.ts', '.js'], fallback: { + assert: require.resolve('assert/'), crypto: false, os: false, fs: false, diff --git a/boxes/init/.yarnrc.yml b/boxes/init/.yarnrc.yml deleted file mode 100644 index 3186f3f0795..00000000000 --- a/boxes/init/.yarnrc.yml +++ /dev/null @@ -1 +0,0 @@ -nodeLinker: node-modules diff --git a/boxes/init/package.json b/boxes/init/package.json deleted file mode 100644 index 12bd80ead44..00000000000 --- a/boxes/init/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "packageManager": "yarn@4.2.2", - "type": "module", - "dependencies": { - "@aztec/accounts": "latest", - "@aztec/aztec.js": "latest", - "@aztec/builder": "latest" - } -} diff --git a/boxes/package.json b/boxes/package.json index 7e5470a3c25..7cd31f064ca 100644 --- a/boxes/package.json +++ b/boxes/package.json @@ -1,13 +1,15 @@ { "name": "aztec-app", "packageManager": "yarn@4.0.2", - "version": "0.4.9", + "version": "0.5.0", "type": "module", "scripts": { "compile": "yarn workspaces foreach -A -v run compile", "build": "yarn workspaces foreach -A -v run build", "install-browsers": "playwright install --with-deps", - "publish": "yarn npm publish" + "publish": "yarn npm publish", + "test": "vitest bin.test.js", + "test:ci": "vitest run bin.test.js" }, "workspaces": [ "boxes/*" @@ -35,9 +37,10 @@ "ora": "^8.0.1", "pino": "^8.19.0", "pino-pretty": "^10.3.1", - "tiged": "^2.12.6" + "tiged": "^2.12.6", + "vitest": "^2.0.5" }, "devDependencies": { - "@playwright/test": "1.42.0" + "@playwright/test": "1.46.1" } } diff --git a/boxes/scripts/steps/sandbox/install.js b/boxes/scripts/steps/sandbox/install.js deleted file mode 100644 index f5de5cbd0f2..00000000000 --- a/boxes/scripts/steps/sandbox/install.js +++ /dev/null @@ -1,113 +0,0 @@ -import confirm from "@inquirer/confirm"; -import { execSync } from "child_process"; - -export async function install() { - execSync( - "curl -s install.aztec.network | NON_INTERACTIVE=1 BIN_PATH=$HOME/.aztec/bin bash -s", - ); -} - -export async function update() { - execSync("$HOME/.aztec/bin/aztec-up", { stdio: "inherit" }); -} - -function findOutUserVersion() { - /** - * We know user has docker installed. - * Now we get the result of the docker image inspect command - * If it throws with an empty object, that's because the image doesn't exist so the user - * Doesn't have the sandbox installed. We exit early since there's nothing to parse. - * - * If it returns an object, we parse the COMMIT_TAG field - * - If there's anything there, that's the version of the sandbox - * - If there's nothing there, that's because there's no tag yet, so he's on master - */ - let sandboxVersion = null; - let dockerOutput = null; - try { - dockerOutput = execSync( - "docker image inspect --format '{{json .Config.Env}}' aztecprotocol/aztec 2>&1", - { - encoding: "utf8", - }, - ); - } catch (error) { - // Something went wrong with the docker command - // So we assume sandbox is not installed - sandboxVersion = null; - } - - if (!dockerOutput) return sandboxVersion; - - // parsing the docker output to get the commit tag - sandboxVersion = JSON.parse(dockerOutput) - .find((env) => env.includes("COMMIT_TAG")) - .split("=")[1]; - - // There's no tag yet, so the user is on master - if (!sandboxVersion) sandboxVersion = "master"; - - return sandboxVersion; -} - -export async function sandboxInstallOrUpdate() { - // Checking for docker - try { - execSync("docker info >/dev/null 2>&1"); - } catch (e) { - error( - "Doesn't seem like Docker is installed or running. Please start it or visit https://docs.aztec.network for more information", - ); - process.exit(1); - } - - // Let's get which version of the sandbox the user has installed - const sandboxVersion = findOutUserVersion(); - - // Base case is that the user doesn't have the sandbox installed - if (sandboxVersion == null) { - const answer = await confirm({ - message: - "Seems like you don't have the Aztec Sandbox installed. Do you want to install it?", - default: true, - }); - if (answer) { - await install(); - } - } else if ( - // Another situation is where the sandbox matches the stable version (i.e. 0.24.0) or master - (sandboxVersion === latestStable || sandboxVersion === "master") && - // but the user has chosen a different version (i.e. "master", 0.23.0, etc) - sandboxVersion !== version - ) { - const answer = await confirm({ - message: `The sandbox is version ${sandboxVersion} but your chosen version is ${version}. Do you want to install version ${version}?`, - default: true, - }); - - if (answer) { - // cool thing is that user already has VERSION in the path, so we don't need to pass it here too - execSync(`$HOME/.aztec/bin/aztec-up`, { stdio: "inherit" }); - } - } else if ( - // Finally, there's a situation where - // the user didn't want any specific version - sandboxVersion !== version && - // and the sandbox is not up to date - // so we need to update to that since the cloned repo is also the latest - sandboxVersion !== latestStable && - // we're also aware that the user might be on master - // so his version is actually not outdated! - version !== "master" - ) { - const answer = await confirm({ - message: `The Sandbox is not up to date. Do you want to update it to ${latestStable}?`, - default: true, - }); - - if (answer) { - // again abusing the fact that the user has VERSION in the path - update(); - } - } -} diff --git a/boxes/scripts/steps/sandbox/run.js b/boxes/scripts/steps/sandbox/run.js deleted file mode 100644 index eb6d00bf7c2..00000000000 --- a/boxes/scripts/steps/sandbox/run.js +++ /dev/null @@ -1,39 +0,0 @@ -import confirm from "@inquirer/confirm"; -import axios from "axios"; - -export async function sandboxRunStep() { - spinner.text = "Trying to reach the sandbox..."; - - try { - spinner.start(); - await axios.post( - "http://localhost:8080", - JSON.stringify({ - jsonrpc: "2.0", - method: "node_getVersion", - id: "null", - }), - { - headers: { - Accept: "*/*", - "Content-Type": "application/json", - }, - }, - ); - spinner.succeed(); - success("The Sandbox is already running!"); - process.exit(0); - } catch (error) { - spinner.fail(); - const answer = await confirm({ - message: - "Sandbox can't be reached on localhost:8080. Do you want to start it?", - default: true, - }); - if (answer) { - info("Starting the sandbox... This might take a few minutes."); - info(`Go and explore the boilerplate code while you wait!`); - start(); - } - } -} diff --git a/boxes/yarn.lock b/boxes/yarn.lock index f23951cf713..f3726279f96 100644 --- a/boxes/yarn.lock +++ b/boxes/yarn.lock @@ -5,7 +5,7 @@ __metadata: version: 8 cacheKey: 10c0 -"@ampproject/remapping@npm:^2.2.0": +"@ampproject/remapping@npm:^2.2.0, @ampproject/remapping@npm:^2.3.0": version: 2.3.0 resolution: "@ampproject/remapping@npm:2.3.0" dependencies: @@ -28,35 +28,18 @@ __metadata: linkType: soft "@aztec/builder@npm:latest": - version: 0.36.0 - resolution: "@aztec/builder@npm:0.36.0" + version: 0.52.0 + resolution: "@aztec/builder@npm:0.52.0" dependencies: - "@aztec/circuits.js": "npm:0.36.0" - "@aztec/foundation": "npm:0.36.0" - "@aztec/types": "npm:0.36.0" - "@iarna/toml": "npm:^2.2.5" - base64-js: "npm:^1.5.1" - commander: "npm:^9.0.0" - fs-extra: "npm:^11.1.1" - lodash.camelcase: "npm:^4.3.0" - lodash.capitalize: "npm:^4.2.1" - memfs: "npm:^4.6.0" - pako: "npm:^2.1.0" - semver: "npm:^7.5.4" - tslib: "npm:^2.4.0" - unzipit: "npm:^1.4.3" + "@aztec/foundation": "npm:0.52.0" + "@aztec/types": "npm:0.52.0" + commander: "npm:^12.1.0" bin: - aztec-builder: dest/cli.js - checksum: 09e61ce771ed94fdf4fc6a9d9bb9953bbeeef1b36449d2546849e5fcd8525b4a663b696dce88e0423b30a69d61c4c21ceca0bbaa003324cd3ac9a8263c0aff63 + aztec-builder: dest/bin/cli.js + checksum: 2207259255fc3e2ffbbd08829f2a4adc9070befaf09e0541213beaf378632a501c29104e447f310aebbf65a21e3cb77b99259a4122e9253640ee232ce4413675 languageName: node linkType: hard -"@aztec/circuits.js@link:../yarn-project/circuits.js::locator=aztec-app%40workspace%3A.": - version: 0.0.0-use.local - resolution: "@aztec/circuits.js@link:../yarn-project/circuits.js::locator=aztec-app%40workspace%3A." - languageName: node - linkType: soft - "@aztec/foundation@link:../yarn-project/foundation::locator=aztec-app%40workspace%3A.": version: 0.0.0-use.local resolution: "@aztec/foundation@link:../yarn-project/foundation::locator=aztec-app%40workspace%3A." @@ -70,13 +53,14 @@ __metadata: "@aztec/accounts": "npm:latest" "@aztec/aztec.js": "npm:latest" "@aztec/builder": "npm:latest" - "@playwright/test": "npm:1.42.0" + "@playwright/test": "npm:1.46.1" "@types/jest": "npm:^29.5.0" "@types/node": "npm:^20.5.9" "@types/react": "npm:^18.2.15" "@types/react-dom": "npm:^18.2.7" "@typescript-eslint/eslint-plugin": "npm:^6.0.0" "@typescript-eslint/parser": "npm:^6.0.0" + assert: "npm:^2.1.0" autoprefixer: "npm:^10.4.15" classnames: "npm:^2.3.2" copy-webpack-plugin: "npm:^11.0.0" @@ -126,8 +110,9 @@ __metadata: "@aztec/accounts": "npm:latest" "@aztec/aztec.js": "npm:latest" "@aztec/builder": "npm:latest" - "@playwright/test": "npm:1.42.0" + "@playwright/test": "npm:1.46.1" "@types/node": "npm:^20.11.17" + assert: "npm:^2.1.0" copy-webpack-plugin: "npm:^11.0.0" html-webpack-plugin: "npm:^5.6.0" stream-browserify: "npm:^3.0.0" @@ -140,203 +125,163 @@ __metadata: languageName: unknown linkType: soft -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.24.2": - version: 7.24.2 - resolution: "@babel/code-frame@npm:7.24.2" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/code-frame@npm:7.24.7" dependencies: - "@babel/highlight": "npm:^7.24.2" + "@babel/highlight": "npm:^7.24.7" picocolors: "npm:^1.0.0" - checksum: d1d4cba89475ab6aab7a88242e1fd73b15ecb9f30c109b69752956434d10a26a52cbd37727c4eca104b6d45227bd1dfce39a6a6f4a14c9b2f07f871e968cf406 + checksum: ab0af539473a9f5aeaac7047e377cb4f4edd255a81d84a76058595f8540784cc3fbe8acf73f1e073981104562490aabfb23008cd66dc677a456a4ed5390fdde6 languageName: node linkType: hard -"@babel/compat-data@npm:^7.23.5": - version: 7.24.4 - resolution: "@babel/compat-data@npm:7.24.4" - checksum: 9cd8a9cd28a5ca6db5d0e27417d609f95a8762b655e8c9c97fd2de08997043ae99f0139007083c5e607601c6122e8432c85fe391731b19bf26ad458fa0c60dd3 +"@babel/compat-data@npm:^7.25.2": + version: 7.25.4 + resolution: "@babel/compat-data@npm:7.25.4" + checksum: 50d79734d584a28c69d6f5b99adfaa064d0f41609a378aef04eb06accc5b44f8520e68549eba3a082478180957b7d5783f1bfb1672e4ae8574e797ce8bae79fa languageName: node linkType: hard "@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9": - version: 7.24.5 - resolution: "@babel/core@npm:7.24.5" + version: 7.25.2 + resolution: "@babel/core@npm:7.25.2" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.24.2" - "@babel/generator": "npm:^7.24.5" - "@babel/helper-compilation-targets": "npm:^7.23.6" - "@babel/helper-module-transforms": "npm:^7.24.5" - "@babel/helpers": "npm:^7.24.5" - "@babel/parser": "npm:^7.24.5" - "@babel/template": "npm:^7.24.0" - "@babel/traverse": "npm:^7.24.5" - "@babel/types": "npm:^7.24.5" + "@babel/code-frame": "npm:^7.24.7" + "@babel/generator": "npm:^7.25.0" + "@babel/helper-compilation-targets": "npm:^7.25.2" + "@babel/helper-module-transforms": "npm:^7.25.2" + "@babel/helpers": "npm:^7.25.0" + "@babel/parser": "npm:^7.25.0" + "@babel/template": "npm:^7.25.0" + "@babel/traverse": "npm:^7.25.2" + "@babel/types": "npm:^7.25.2" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: e26ba810a77bc8e21579a12fc36c79a0a60554404dc9447f2d64eb1f26d181c48d3b97d39d9f158e9911ec7162a8280acfaf2b4b210e975f0dd4bd4dbb1ee159 + checksum: a425fa40e73cb72b6464063a57c478bc2de9dbcc19c280f1b55a3d88b35d572e87e8594e7d7b4880331addb6faef641bbeb701b91b41b8806cd4deae5d74f401 languageName: node linkType: hard -"@babel/generator@npm:^7.24.5, @babel/generator@npm:^7.7.2": - version: 7.24.5 - resolution: "@babel/generator@npm:7.24.5" +"@babel/generator@npm:^7.25.0, @babel/generator@npm:^7.25.6, @babel/generator@npm:^7.7.2": + version: 7.25.6 + resolution: "@babel/generator@npm:7.25.6" dependencies: - "@babel/types": "npm:^7.24.5" + "@babel/types": "npm:^7.25.6" "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^2.5.1" - checksum: 0d64f880150e7dfb92ceff2b4ac865f36aa1e295120920246492ffd0146562dabf79ba8699af1c8833f8a7954818d4d146b7b02f808df4d6024fb99f98b2f78d + checksum: f89282cce4ddc63654470b98086994d219407d025497f483eb03ba102086e11e2b685b27122f6ff2e1d93b5b5fa0c3a6b7e974fbf2e4a75b685041a746a4291e languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/helper-compilation-targets@npm:7.23.6" +"@babel/helper-compilation-targets@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/helper-compilation-targets@npm:7.25.2" dependencies: - "@babel/compat-data": "npm:^7.23.5" - "@babel/helper-validator-option": "npm:^7.23.5" - browserslist: "npm:^4.22.2" + "@babel/compat-data": "npm:^7.25.2" + "@babel/helper-validator-option": "npm:^7.24.8" + browserslist: "npm:^4.23.1" lru-cache: "npm:^5.1.1" semver: "npm:^6.3.1" - checksum: ba38506d11185f48b79abf439462ece271d3eead1673dd8814519c8c903c708523428806f05f2ec5efd0c56e4e278698fac967e5a4b5ee842c32415da54bc6fa - languageName: node - linkType: hard - -"@babel/helper-environment-visitor@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-environment-visitor@npm:7.22.20" - checksum: e762c2d8f5d423af89bd7ae9abe35bd4836d2eb401af868a63bbb63220c513c783e25ef001019418560b3fdc6d9a6fb67e6c0b650bcdeb3a2ac44b5c3d2bdd94 - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/helper-function-name@npm:7.23.0" - dependencies: - "@babel/template": "npm:^7.22.15" - "@babel/types": "npm:^7.23.0" - checksum: d771dd1f3222b120518176733c52b7cadac1c256ff49b1889dbbe5e3fed81db855b8cc4e40d949c9d3eae0e795e8229c1c8c24c0e83f27cfa6ee3766696c6428 + checksum: de10e986b5322c9f807350467dc845ec59df9e596a5926a3b5edbb4710d8e3b8009d4396690e70b88c3844fe8ec4042d61436dd4b92d1f5f75655cf43ab07e99 languageName: node linkType: hard -"@babel/helper-hoist-variables@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-hoist-variables@npm:7.22.5" +"@babel/helper-module-imports@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-module-imports@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 60a3077f756a1cd9f14eb89f0037f487d81ede2b7cfe652ea6869cd4ec4c782b0fb1de01b8494b9a2d2050e3d154d7d5ad3be24806790acfb8cbe2073bf1e208 + "@babel/traverse": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 97c57db6c3eeaea31564286e328a9fb52b0313c5cfcc7eee4bc226aebcf0418ea5b6fe78673c0e4a774512ec6c86e309d0f326e99d2b37bfc16a25a032498af0 languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.24.3": - version: 7.24.3 - resolution: "@babel/helper-module-imports@npm:7.24.3" +"@babel/helper-module-transforms@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/helper-module-transforms@npm:7.25.2" dependencies: - "@babel/types": "npm:^7.24.0" - checksum: 052c188adcd100f5e8b6ff0c9643ddaabc58b6700d3bbbc26804141ad68375a9f97d9d173658d373d31853019e65f62610239e3295cdd58e573bdcb2fded188d - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helper-module-transforms@npm:7.24.5" - dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-module-imports": "npm:^7.24.3" - "@babel/helper-simple-access": "npm:^7.24.5" - "@babel/helper-split-export-declaration": "npm:^7.24.5" - "@babel/helper-validator-identifier": "npm:^7.24.5" + "@babel/helper-module-imports": "npm:^7.24.7" + "@babel/helper-simple-access": "npm:^7.24.7" + "@babel/helper-validator-identifier": "npm:^7.24.7" + "@babel/traverse": "npm:^7.25.2" peerDependencies: "@babel/core": ^7.0.0 - checksum: 6e77d72f62b7e87abaea800ea0bccd4d54cde26485750969f5f493c032eb63251eb50c3522cace557781565d51c1d0c4bcc866407d24becfb109c18fb92c978d + checksum: adaa15970ace0aee5934b5a633789b5795b6229c6a9cf3e09a7e80aa33e478675eee807006a862aa9aa517935d81f88a6db8a9f5936e3a2a40ec75f8062bc329 languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.24.0, @babel/helper-plugin-utils@npm:^7.8.0": - version: 7.24.5 - resolution: "@babel/helper-plugin-utils@npm:7.24.5" - checksum: 4ae40094e6a2f183281213344f4df60c66b16b19a2bc38d2bb11810a6dc0a0e7ec638957d0e433ff8b615775b8f3cd1b7edbf59440d1b50e73c389fc22913377 +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.8.0": + version: 7.24.8 + resolution: "@babel/helper-plugin-utils@npm:7.24.8" + checksum: 0376037f94a3bfe6b820a39f81220ac04f243eaee7193774b983e956c1750883ff236b30785795abbcda43fac3ece74750566830c2daa4d6e3870bb0dff34c2d languageName: node linkType: hard -"@babel/helper-simple-access@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helper-simple-access@npm:7.24.5" +"@babel/helper-simple-access@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-simple-access@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.24.5" - checksum: d96a0ab790a400f6c2dcbd9457b9ca74b9ba6d0f67ff9cd5bcc73792c8fbbd0847322a0dddbd8987dd98610ee1637c680938c7d83d3ffce7d06d7519d823d996 + "@babel/traverse": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 7230e419d59a85f93153415100a5faff23c133d7442c19e0cd070da1784d13cd29096ee6c5a5761065c44e8164f9f80e3a518c41a0256df39e38f7ad6744fed7 languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helper-split-export-declaration@npm:7.24.5" - dependencies: - "@babel/types": "npm:^7.24.5" - checksum: d7a812d67d031a348f3fb0e6263ce2dbe6038f81536ba7fb16db385383bcd6542b71833194303bf6d3d0e4f7b6b584c9c8fae8772122e2ce68fc9bdf07f4135d +"@babel/helper-string-parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-string-parser@npm:7.24.8" + checksum: 6361f72076c17fabf305e252bf6d580106429014b3ab3c1f5c4eb3e6d465536ea6b670cc0e9a637a77a9ad40454d3e41361a2909e70e305116a23d68ce094c08 languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.23.4, @babel/helper-string-parser@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/helper-string-parser@npm:7.24.1" - checksum: 2f9bfcf8d2f9f083785df0501dbab92770111ece2f90d120352fda6dd2a7d47db11b807d111e6f32aa1ba6d763fe2dc6603d153068d672a5d0ad33ca802632b2 +"@babel/helper-validator-identifier@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-validator-identifier@npm:7.24.7" + checksum: 87ad608694c9477814093ed5b5c080c2e06d44cb1924ae8320474a74415241223cc2a725eea2640dd783ff1e3390e5f95eede978bc540e870053152e58f1d651 languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-validator-identifier@npm:7.22.20" - checksum: dcad63db345fb110e032de46c3688384b0008a42a4845180ce7cd62b1a9c0507a1bed727c4d1060ed1a03ae57b4d918570259f81724aaac1a5b776056f37504e +"@babel/helper-validator-option@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-validator-option@npm:7.24.8" + checksum: 73db93a34ae89201351288bee7623eed81a54000779462a986105b54ffe82069e764afd15171a428b82e7c7a9b5fec10b5d5603b216317a414062edf5c67a21f languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helper-validator-identifier@npm:7.24.5" - checksum: 05f957229d89ce95a137d04e27f7d0680d84ae48b6ad830e399db0779341f7d30290f863a93351b4b3bde2166737f73a286ea42856bb07c8ddaa95600d38645c - languageName: node - linkType: hard - -"@babel/helper-validator-option@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/helper-validator-option@npm:7.23.5" - checksum: af45d5c0defb292ba6fd38979e8f13d7da63f9623d8ab9ededc394f67eb45857d2601278d151ae9affb6e03d5d608485806cd45af08b4468a0515cf506510e94 - languageName: node - linkType: hard - -"@babel/helpers@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helpers@npm:7.24.5" +"@babel/helpers@npm:^7.25.0": + version: 7.25.6 + resolution: "@babel/helpers@npm:7.25.6" dependencies: - "@babel/template": "npm:^7.24.0" - "@babel/traverse": "npm:^7.24.5" - "@babel/types": "npm:^7.24.5" - checksum: 0630b0223c3a9a34027ddc05b3bac54d68d5957f84e92d2d4814b00448a76e12f9188f9c85cfce2011696d82a8ffcbd8189da097c0af0181d32eb27eca34185e + "@babel/template": "npm:^7.25.0" + "@babel/types": "npm:^7.25.6" + checksum: 448c1cdabccca42fd97a252f73f1e4bcd93776dbf24044f3b4f49b756bf2ece73ee6df05177473bb74ea7456dddd18d6f481e4d96d2cc7839d078900d48c696c languageName: node linkType: hard -"@babel/highlight@npm:^7.24.2": - version: 7.24.5 - resolution: "@babel/highlight@npm:7.24.5" +"@babel/highlight@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/highlight@npm:7.24.7" dependencies: - "@babel/helper-validator-identifier": "npm:^7.24.5" + "@babel/helper-validator-identifier": "npm:^7.24.7" chalk: "npm:^2.4.2" js-tokens: "npm:^4.0.0" picocolors: "npm:^1.0.0" - checksum: e98047d3ad24608bfa596d000c861a2cc875af897427f2833b91a4e0d4cead07301a7ec15fa26093dcd61e036e2eed2db338ae54f93016fe0dc785fadc4159db + checksum: 674334c571d2bb9d1c89bdd87566383f59231e16bcdcf5bb7835babdf03c9ae585ca0887a7b25bdf78f303984af028df52831c7989fecebb5101cc132da9393a languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.0, @babel/parser@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/parser@npm:7.24.5" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.25.0, @babel/parser@npm:^7.25.6": + version: 7.25.6 + resolution: "@babel/parser@npm:7.25.6" + dependencies: + "@babel/types": "npm:^7.25.6" bin: parser: ./bin/babel-parser.js - checksum: 8333a6ad5328bad34fa0e12bcee147c3345ea9a438c0909e7c68c6cfbea43c464834ffd7eabd1cbc1c62df0a558e22ffade9f5b29440833ba7b33d96a71f88c0 + checksum: f88a0e895dbb096fd37c4527ea97d12b5fc013720602580a941ac3a339698872f0c911e318c292b184c36b5fbe23b612f05aff9d24071bc847c7b1c21552c41d languageName: node linkType: hard @@ -362,7 +307,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-class-properties@npm:^7.8.3": +"@babel/plugin-syntax-class-properties@npm:^7.12.13": version: 7.12.13 resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" dependencies: @@ -373,7 +318,29 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-meta@npm:^7.8.3": +"@babel/plugin-syntax-class-static-block@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4464bf9115f4a2d02ce1454411baf9cfb665af1da53709c5c56953e5e2913745b0fcce82982a00463d6facbdd93445c691024e310b91431a1e2f024b158f6371 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-attributes@npm:^7.24.7": + version: 7.25.6 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.25.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.24.8" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0e9359cf2d117476310961dfcfd7204ed692e933707da10d6194153d3996cd2ea5b7635fc90d720dce3612083af89966bb862561064a509c350320dc98644751 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-meta@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" dependencies: @@ -396,17 +363,17 @@ __metadata: linkType: hard "@babel/plugin-syntax-jsx@npm:^7.7.2": - version: 7.24.1 - resolution: "@babel/plugin-syntax-jsx@npm:7.24.1" + version: 7.24.7 + resolution: "@babel/plugin-syntax-jsx@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 6cec76fbfe6ca81c9345c2904d8d9a8a0df222f9269f0962ed6eb2eb8f3f10c2f15e993d1ef09dbaf97726bf1792b5851cf5bd9a769f966a19448df6be95d19a + checksum: f44d927a9ae8d5ef016ff5b450e1671e56629ddc12e56b938e41fd46e141170d9dfc9a53d6cb2b9a20a7dd266a938885e6a3981c60c052a2e1daed602ac80e51 languageName: node linkType: hard -"@babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" dependencies: @@ -428,7 +395,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-numeric-separator@npm:^7.8.3": +"@babel/plugin-syntax-numeric-separator@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" dependencies: @@ -472,7 +439,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-top-level-await@npm:^7.8.3": +"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.14.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 69822772561706c87f0a65bc92d0772cea74d6bc0911537904a676d5ff496a6d3ac4e05a166d8125fce4a16605bace141afc3611074e170a994e66e5397787f3 + languageName: node + linkType: hard + +"@babel/plugin-syntax-top-level-await@npm:^7.14.5": version: 7.14.5 resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" dependencies: @@ -484,64 +462,50 @@ __metadata: linkType: hard "@babel/plugin-syntax-typescript@npm:^7.7.2": - version: 7.24.1 - resolution: "@babel/plugin-syntax-typescript@npm:7.24.1" + version: 7.25.4 + resolution: "@babel/plugin-syntax-typescript@npm:7.25.4" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.8" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7a81e277dcfe3138847e8e5944e02a42ff3c2e864aea6f33fd9b70d1556d12b0e70f0d56cc1985d353c91bcbf8fe163e6cc17418da21129b7f7f1d8b9ac00c93 + checksum: 199919d44c73e5edee9ffd311cf638f88d26a810189e32d338c46c7600441fd5c4a2e431f9be377707cbf318410895304e90b83bf8d9011d205150fa7f260e63 languageName: node linkType: hard -"@babel/template@npm:^7.22.15, @babel/template@npm:^7.24.0, @babel/template@npm:^7.3.3": - version: 7.24.0 - resolution: "@babel/template@npm:7.24.0" +"@babel/template@npm:^7.25.0, @babel/template@npm:^7.3.3": + version: 7.25.0 + resolution: "@babel/template@npm:7.25.0" dependencies: - "@babel/code-frame": "npm:^7.23.5" - "@babel/parser": "npm:^7.24.0" - "@babel/types": "npm:^7.24.0" - checksum: 9d3dd8d22fe1c36bc3bdef6118af1f4b030aaf6d7d2619f5da203efa818a2185d717523486c111de8d99a8649ddf4bbf6b2a7a64962d8411cf6a8fa89f010e54 + "@babel/code-frame": "npm:^7.24.7" + "@babel/parser": "npm:^7.25.0" + "@babel/types": "npm:^7.25.0" + checksum: 4e31afd873215744c016e02b04f43b9fa23205d6d0766fb2e93eb4091c60c1b88897936adb895fb04e3c23de98dfdcbe31bc98daaa1a4e0133f78bb948e1209b languageName: node linkType: hard -"@babel/traverse@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/traverse@npm:7.24.5" +"@babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.25.2": + version: 7.25.6 + resolution: "@babel/traverse@npm:7.25.6" dependencies: - "@babel/code-frame": "npm:^7.24.2" - "@babel/generator": "npm:^7.24.5" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.24.5" - "@babel/parser": "npm:^7.24.5" - "@babel/types": "npm:^7.24.5" + "@babel/code-frame": "npm:^7.24.7" + "@babel/generator": "npm:^7.25.6" + "@babel/parser": "npm:^7.25.6" + "@babel/template": "npm:^7.25.0" + "@babel/types": "npm:^7.25.6" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 3f22534bc2b2ed9208e55ef48af3b32939032b23cb9dc4037447cb108640df70bbb0b9fea86e9c58648949fdc2cb14e89aa79ffa3c62a5dd43459a52fe8c01d1 + checksum: 964304c6fa46bd705428ba380bf73177eeb481c3f26d82ea3d0661242b59e0dd4329d23886035e9ca9a4ceb565c03a76fd615109830687a27bcd350059d6377e languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.24.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.8.3": - version: 7.24.0 - resolution: "@babel/types@npm:7.24.0" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.25.0, @babel/types@npm:^7.25.2, @babel/types@npm:^7.25.6, @babel/types@npm:^7.3.3": + version: 7.25.6 + resolution: "@babel/types@npm:7.25.6" dependencies: - "@babel/helper-string-parser": "npm:^7.23.4" - "@babel/helper-validator-identifier": "npm:^7.22.20" + "@babel/helper-string-parser": "npm:^7.24.8" + "@babel/helper-validator-identifier": "npm:^7.24.7" to-fast-properties: "npm:^2.0.0" - checksum: 777a0bb5dbe038ca4c905fdafb1cdb6bdd10fe9d63ce13eca0bd91909363cbad554a53dc1f902004b78c1dcbc742056f877f2c99eeedff647333b1fadf51235d - languageName: node - linkType: hard - -"@babel/types@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/types@npm:7.24.5" - dependencies: - "@babel/helper-string-parser": "npm:^7.24.1" - "@babel/helper-validator-identifier": "npm:^7.24.5" - to-fast-properties: "npm:^2.0.0" - checksum: e1284eb046c5e0451b80220d1200e2327e0a8544a2fe45bb62c952e5fdef7099c603d2336b17b6eac3cc046b7a69bfbce67fe56e1c0ea48cd37c65cb88638f2a + checksum: 89d45fbee24e27a05dca2d08300a26b905bd384a480448823f6723c72d3a30327c517476389b7280ce8cb9a2c48ef8f47da7f9f6d326faf6f53fd6b68237bdc4 languageName: node linkType: hard @@ -568,6 +532,167 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/aix-ppc64@npm:0.21.5" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm64@npm:0.21.5" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm@npm:0.21.5" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@esbuild/android-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-x64@npm:0.21.5" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/darwin-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-arm64@npm:0.21.5" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/darwin-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-x64@npm:0.21.5" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-arm64@npm:0.21.5" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/freebsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-x64@npm:0.21.5" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/linux-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm64@npm:0.21.5" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm@npm:0.21.5" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@esbuild/linux-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ia32@npm:0.21.5" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-loong64@npm:0.21.5" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@esbuild/linux-mips64el@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-mips64el@npm:0.21.5" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@esbuild/linux-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ppc64@npm:0.21.5" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-riscv64@npm:0.21.5" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@esbuild/linux-s390x@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-s390x@npm:0.21.5" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@esbuild/linux-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-x64@npm:0.21.5" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/netbsd-x64@npm:0.21.5" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/openbsd-x64@npm:0.21.5" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/sunos-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/sunos-x64@npm:0.21.5" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-arm64@npm:0.21.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/win32-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-ia32@npm:0.21.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-x64@npm:0.21.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -580,9 +705,9 @@ __metadata: linkType: hard "@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": - version: 4.10.0 - resolution: "@eslint-community/regexpp@npm:4.10.0" - checksum: c5f60ef1f1ea7649fa7af0e80a5a79f64b55a8a8fa5086de4727eb4c86c652aedee407a9c143b8995d2c0b2d75c1222bec9ba5d73dbfc1f314550554f0979ef4 + version: 4.11.0 + resolution: "@eslint-community/regexpp@npm:4.11.0" + checksum: 0f6328869b2741e2794da4ad80beac55cba7de2d3b44f796a60955b0586212ec75e6b0253291fd4aad2100ad471d1480d8895f2b54f1605439ba4c875e05e523 languageName: node linkType: hard @@ -643,70 +768,72 @@ __metadata: linkType: hard "@inquirer/confirm@npm:^3.0.0": - version: 3.1.6 - resolution: "@inquirer/confirm@npm:3.1.6" + version: 3.2.0 + resolution: "@inquirer/confirm@npm:3.2.0" dependencies: - "@inquirer/core": "npm:^8.1.0" - "@inquirer/type": "npm:^1.3.1" - checksum: 2d13daf4587d1073935edb6c24cec00f738b3c5401bdd8047b50a2bf7410bbc84ded78ff934a2266cbd022d52b0aa8611821bda198d1e54fafca4c0ed25be38a + "@inquirer/core": "npm:^9.1.0" + "@inquirer/type": "npm:^1.5.3" + checksum: a2cbfc8ae9c880bba4cce1993f5c399fb0d12741fdd574917c87fceb40ece62ffa60e35aaadf4e62d7c114f54008e45aee5d6d90497bb62d493996c02725d243 languageName: node linkType: hard -"@inquirer/core@npm:^8.1.0": - version: 8.1.0 - resolution: "@inquirer/core@npm:8.1.0" +"@inquirer/core@npm:^9.1.0": + version: 9.1.0 + resolution: "@inquirer/core@npm:9.1.0" dependencies: - "@inquirer/figures": "npm:^1.0.1" - "@inquirer/type": "npm:^1.3.1" + "@inquirer/figures": "npm:^1.0.5" + "@inquirer/type": "npm:^1.5.3" "@types/mute-stream": "npm:^0.0.4" - "@types/node": "npm:^20.12.7" + "@types/node": "npm:^22.5.2" "@types/wrap-ansi": "npm:^3.0.0" ansi-escapes: "npm:^4.3.2" - chalk: "npm:^4.1.2" cli-spinners: "npm:^2.9.2" cli-width: "npm:^4.1.0" mute-stream: "npm:^1.0.0" signal-exit: "npm:^4.1.0" strip-ansi: "npm:^6.0.1" wrap-ansi: "npm:^6.2.0" - checksum: 5746830c672f24505d7554fe43f05f97823fdf1c84aaeab1808dc09911e748f6b1887902794d95239655c0ed5f6029c2b3c018ab7c2785427ae95a4e92faa4d7 + yoctocolors-cjs: "npm:^2.1.2" + checksum: c86cbd1980788dee4151002ed717b5664a79eec1d925e1b38896bbad079647af5c423eaaa39a2291ba4fdf78a33c541ea3f69cbbf030f03815eb523fa05230f8 languageName: node linkType: hard -"@inquirer/figures@npm:^1.0.1": - version: 1.0.1 - resolution: "@inquirer/figures@npm:1.0.1" - checksum: a1e9d3852e0d33c416eb39d7ee0e898971681a0a5a0d2fad5ebbb63047dd7e8b7bd32872cf2ef09578ce632bd9cc339f7e851dbd4640a9af11224481bf811e14 +"@inquirer/figures@npm:^1.0.5": + version: 1.0.5 + resolution: "@inquirer/figures@npm:1.0.5" + checksum: ec9ba23db42cb33fa18eb919abf2a18e750e739e64c1883ce4a98345cd5711c60cac12d1faf56a859f52d387deb221c8d3dfe60344ee07955a9a262f8b821fe3 languageName: node linkType: hard "@inquirer/input@npm:^2.0.0": - version: 2.1.6 - resolution: "@inquirer/input@npm:2.1.6" + version: 2.3.0 + resolution: "@inquirer/input@npm:2.3.0" dependencies: - "@inquirer/core": "npm:^8.1.0" - "@inquirer/type": "npm:^1.3.1" - checksum: 0184074a762c236e40b2d1c205653bf1ec7da5f16c980a59d3c9dcec89474553af17b1a3b50e54ec9e3b23fc8417b8ac51022bd562b789e8471db06bd44c946d + "@inquirer/core": "npm:^9.1.0" + "@inquirer/type": "npm:^1.5.3" + checksum: 44c8cea38c9192f528cae556f38709135a00230132deab3b9bb9a925375fce0513fecf4e8c1df7c4319e1ed7aa31fb4dd2c4956c8bc9dd39af087aafff5b6f1f languageName: node linkType: hard "@inquirer/select@npm:^2.0.0": - version: 2.3.2 - resolution: "@inquirer/select@npm:2.3.2" + version: 2.5.0 + resolution: "@inquirer/select@npm:2.5.0" dependencies: - "@inquirer/core": "npm:^8.1.0" - "@inquirer/figures": "npm:^1.0.1" - "@inquirer/type": "npm:^1.3.1" + "@inquirer/core": "npm:^9.1.0" + "@inquirer/figures": "npm:^1.0.5" + "@inquirer/type": "npm:^1.5.3" ansi-escapes: "npm:^4.3.2" - chalk: "npm:^4.1.2" - checksum: 5c2badca6fd8ed27c44a89009a9c9918030095734bb0dad0826a5a5d4863e2e53facb6a28fc387cff77156a1cffe80e6c3b84e0a0e3757d34f275db39cfad0a6 + yoctocolors-cjs: "npm:^2.1.2" + checksum: 280fa700187ff29da0ad4bf32aa11db776261584ddf5cc1ceac5caebb242a4ac0c5944af522a2579d78b6ec7d6e8b1b9f6564872101abd8dcc69929b4e33fc4c languageName: node linkType: hard -"@inquirer/type@npm:^1.3.1": - version: 1.3.1 - resolution: "@inquirer/type@npm:1.3.1" - checksum: 7dbf7ca10f758f2b6dbc7b7302ce01e79596747692468805c340afa0bf608adecbe33cd3c3b2b806bb3987cadf233b52ead7652b479a052455bc06855849f97f +"@inquirer/type@npm:^1.5.3": + version: 1.5.3 + resolution: "@inquirer/type@npm:1.5.3" + dependencies: + mute-stream: "npm:^1.0.0" + checksum: da92a7410efcb20cf12422558fb8e00136e2ff1746ae1d17ea05511e77139bf2044527d37a70e77f188f158099f7751ed808ca3f82769cbe99c1052509481e95 languageName: node linkType: hard @@ -1009,10 +1136,10 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": - version: 1.4.15 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" - checksum: 0c6b5ae663087558039052a626d2d7ed5208da36cfd707dcc5cea4a07cfc918248403dcb5989a8f7afaf245ce0573b7cc6fd94c4a30453bd10e44d9363940ba5 +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": + version: 1.5.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" + checksum: 2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18 languageName: node linkType: hard @@ -1036,38 +1163,6 @@ __metadata: languageName: node linkType: hard -"@jsonjoy.com/base64@npm:^1.1.1": - version: 1.1.1 - resolution: "@jsonjoy.com/base64@npm:1.1.1" - peerDependencies: - tslib: 2 - checksum: be8d0eb6fe5bf9c4b068949fc9839d6b6b325dcc6a961996a3f64eedb4c8ee8c5073fc834c2c71587890df4e0481dd3ea3a8d948da3d6c7a44b32951b23dc484 - languageName: node - linkType: hard - -"@jsonjoy.com/json-pack@npm:^1.0.3": - version: 1.0.3 - resolution: "@jsonjoy.com/json-pack@npm:1.0.3" - dependencies: - "@jsonjoy.com/base64": "npm:^1.1.1" - "@jsonjoy.com/util": "npm:^1.1.2" - hyperdyperid: "npm:^1.2.0" - thingies: "npm:^1.20.0" - peerDependencies: - tslib: 2 - checksum: 523f3d8df424bf339aa31045275f835985aa9ab27f4defeff4fc644ffd3219dc75011b51634a9ca15bc3fcb2e14c51f7b0d3d97cf4affc145d0d1aad5700900c - languageName: node - linkType: hard - -"@jsonjoy.com/util@npm:^1.1.2": - version: 1.1.2 - resolution: "@jsonjoy.com/util@npm:1.1.2" - peerDependencies: - tslib: 2 - checksum: e9054e8208d75496ec5b5ed6a9a3c8431b8ec378820169c25c86ea4636ff4ae66f9fcc7bed6678c0ee7c0c6452ff0137b3339d9e4829957f3f31656e5b0176a3 - languageName: node - linkType: hard - "@leichtgewicht/ip-codec@npm:^2.0.1": version: 2.0.5 resolution: "@leichtgewicht/ip-codec@npm:2.0.5" @@ -1102,6 +1197,13 @@ __metadata: languageName: node linkType: hard +"@nolyfill/is-core-module@npm:1.0.39": + version: 1.0.39 + resolution: "@nolyfill/is-core-module@npm:1.0.39" + checksum: 34ab85fdc2e0250879518841f74a30c276bca4f6c3e13526d2d1fe515e1adf6d46c25fcd5989d22ea056d76f7c39210945180b4859fc83b050e2da411aa86289 + languageName: node + linkType: hard + "@npmcli/agent@npm:^2.0.0": version: 2.2.2 resolution: "@npmcli/agent@npm:2.2.2" @@ -1116,11 +1218,11 @@ __metadata: linkType: hard "@npmcli/fs@npm:^3.1.0": - version: 3.1.0 - resolution: "@npmcli/fs@npm:3.1.0" + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" dependencies: semver: "npm:^7.3.5" - checksum: 162b4a0b8705cd6f5c2470b851d1dc6cd228c86d2170e1769d738c1fbb69a87160901411c3c035331e9e99db72f1f1099a8b734bf1637cc32b9a5be1660e4e1e + checksum: c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 languageName: node linkType: hard @@ -1138,14 +1240,133 @@ __metadata: languageName: node linkType: hard -"@playwright/test@npm:1.42.0": - version: 1.42.0 - resolution: "@playwright/test@npm:1.42.0" +"@playwright/test@npm:1.46.1": + version: 1.46.1 + resolution: "@playwright/test@npm:1.46.1" dependencies: - playwright: "npm:1.42.0" + playwright: "npm:1.46.1" bin: playwright: cli.js - checksum: 1505544fd4962cc9463c2e0d21958507b4b23ecb835ef19d81a97ae01cda9030585dc321263486cce4d1eac53724615b7b3ec41a94b6c1a54a2b7ed01157de60 + checksum: b2d33f33bedfa5a5c72cfc5ee212dfbf531d9c46320b0af901e71ab61b96845e43cc636181b33b3faae27f2f87ce2d44017ac65235bf9c95209f476477b16f93 + languageName: node + linkType: hard + +"@rollup/rollup-android-arm-eabi@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.21.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-android-arm64@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-android-arm64@npm:4.21.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-arm64@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-darwin-arm64@npm:4.21.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-x64@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-darwin-x64@npm:4.21.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.21.2" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-musleabihf@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.21.2" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.21.2" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.21.2" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.21.2" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.21.2" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-s390x-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.21.2" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.21.2" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-musl@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.21.2" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.21.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-ia32-msvc@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.21.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.21.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@rtsao/scc@npm:^1.1.0": + version: 1.1.0 + resolution: "@rtsao/scc@npm:1.1.0" + checksum: b5bcfb0d87f7d1c1c7c0f7693f53b07866ed9fec4c34a97a8c948fb9a7c0082e416ce4d3b60beb4f5e167cbe04cdeefbf6771320f3ede059b9ce91188c409a5b languageName: node linkType: hard @@ -1235,11 +1456,11 @@ __metadata: linkType: hard "@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": - version: 7.20.5 - resolution: "@types/babel__traverse@npm:7.20.5" + version: 7.20.6 + resolution: "@types/babel__traverse@npm:7.20.6" dependencies: "@babel/types": "npm:^7.20.7" - checksum: 033abcb2f4c084ad33e30c3efaad82161240f351e3c71b6154ed289946b33b363696c0fbd42502b68e4582a87413c418321f40eb1ea863e34fe525641345e05b + checksum: 7ba7db61a53e28cac955aa99af280d2600f15a8c056619c05b6fc911cbe02c61aa4f2823299221b23ce0cce00b294c0e5f618ec772aa3f247523c2e48cf7b888 languageName: node linkType: hard @@ -1281,27 +1502,7 @@ __metadata: languageName: node linkType: hard -"@types/eslint-scope@npm:^3.7.3": - version: 3.7.7 - resolution: "@types/eslint-scope@npm:3.7.7" - dependencies: - "@types/eslint": "npm:*" - "@types/estree": "npm:*" - checksum: a0ecbdf2f03912679440550817ff77ef39a30fa8bfdacaf6372b88b1f931828aec392f52283240f0d648cf3055c5ddc564544a626bcf245f3d09fcb099ebe3cc - languageName: node - linkType: hard - -"@types/eslint@npm:*": - version: 8.56.10 - resolution: "@types/eslint@npm:8.56.10" - dependencies: - "@types/estree": "npm:*" - "@types/json-schema": "npm:*" - checksum: 674349d6c342c3864d70f4d5a9965f96fb253801532752c8c500ad6a1c2e8b219e01ccff5dc8791dcb58b5483012c495708bb9f3ff929f5c9322b3da126c15d3 - languageName: node - linkType: hard - -"@types/estree@npm:*, @types/estree@npm:^1.0.5": +"@types/estree@npm:1.0.5, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5": version: 1.0.5 resolution: "@types/estree@npm:1.0.5" checksum: b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d @@ -1309,14 +1510,14 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33": - version: 4.19.0 - resolution: "@types/express-serve-static-core@npm:4.19.0" + version: 4.19.5 + resolution: "@types/express-serve-static-core@npm:4.19.5" dependencies: "@types/node": "npm:*" "@types/qs": "npm:*" "@types/range-parser": "npm:*" "@types/send": "npm:*" - checksum: 38a13dfbb38d18526276e68dae1097eb0ebef296e76bff2a9bf6831c052c2f87797e910c87bd3f0dd1a1b4136241c9d7c841779a00b22576d12aa9b483a63349 + checksum: ba8d8d976ab797b2602c60e728802ff0c98a00f13d420d82770f3661b67fa36ea9d3be0b94f2ddd632afe1fbc6e41620008b01db7e4fabdd71a2beb5539b0725 languageName: node linkType: hard @@ -1366,11 +1567,11 @@ __metadata: linkType: hard "@types/http-proxy@npm:^1.17.8": - version: 1.17.14 - resolution: "@types/http-proxy@npm:1.17.14" + version: 1.17.15 + resolution: "@types/http-proxy@npm:1.17.15" dependencies: "@types/node": "npm:*" - checksum: c4bffd87be9aff7e879c05bd2c28716220e0eb39788e3f8d314eee665324ad8f5f0919041cbd710254d553cd9cea023f8b776d4b1ec31d2188eac60af18c3022 + checksum: e2bf2fcdf23c88141b8d2c85ed5e5418b62ef78285884a2b5a717af55f4d9062136aa475489d10292093343df58fb81975f34bebd6b9df322288fd9821cbee07 languageName: node linkType: hard @@ -1409,7 +1610,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": +"@types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db @@ -1448,12 +1649,21 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^20.11.17, @types/node@npm:^20.12.7, @types/node@npm:^20.5.9": - version: 20.12.8 - resolution: "@types/node@npm:20.12.8" +"@types/node@npm:*, @types/node@npm:^22.5.2": + version: 22.5.2 + resolution: "@types/node@npm:22.5.2" dependencies: - undici-types: "npm:~5.26.4" - checksum: 840002d20654e38a9af8cdffa215598fdb28ac4f96c5701ed672ec365ed6ccc66da299edddaa409baf13cd71bbf1128901f633b5e44e070fc236e26415805b78 + undici-types: "npm:~6.19.2" + checksum: 624a7fd76229eacc6c158eb3b9afd55b811d7f01976c5f92c630d5b9d47047cc218928c343988484a165ac400e5eb6fe70ea300fc7242deeb0e920c7724290f6 + languageName: node + linkType: hard + +"@types/node@npm:^20.11.17, @types/node@npm:^20.5.9": + version: 20.16.3 + resolution: "@types/node@npm:20.16.3" + dependencies: + undici-types: "npm:~6.19.2" + checksum: 907c01d58ae36695fbed0b101e7a14cc2e0c5b9b2ba7904ef21cef093e4aac0649ac2a7a283fc94e19311dd0551d778445dd45fcf2d8bd45c494c9ecd802de69 languageName: node linkType: hard @@ -1488,12 +1698,12 @@ __metadata: linkType: hard "@types/react@npm:*, @types/react@npm:^18.2.15": - version: 18.3.1 - resolution: "@types/react@npm:18.3.1" + version: 18.3.5 + resolution: "@types/react@npm:18.3.5" dependencies: "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 18d856c12a4ec93f3cda2d58ef3d77a9480818afd3af895f812896fb82cfca1f35a692ab1add4ce826a4eb58a071624c7d1c8c6c4ccfb81c100d2916dc607614 + checksum: 548b1d3d7c2f0242fbfdbbd658731b4ce69a134be072fa83e6ab516f2840402a3f20e3e7f72e95133b23d4880ef24a6d864050dc8e1f7c68f39fa87ca8445917 languageName: node linkType: hard @@ -1565,11 +1775,11 @@ __metadata: linkType: hard "@types/ws@npm:^8.5.5": - version: 8.5.10 - resolution: "@types/ws@npm:8.5.10" + version: 8.5.12 + resolution: "@types/ws@npm:8.5.12" dependencies: "@types/node": "npm:*" - checksum: e9af279b984c4a04ab53295a40aa95c3e9685f04888df5c6920860d1dd073fcc57c7bd33578a04b285b2c655a0b52258d34bee0a20569dca8defb8393e1e5d29 + checksum: 3fd77c9e4e05c24ce42bfc7647f7506b08c40a40fe2aea236ef6d4e96fc7cb4006a81ed1b28ec9c457e177a74a72924f4768b7b4652680b42dfd52bc380e15f9 languageName: node linkType: hard @@ -1581,11 +1791,11 @@ __metadata: linkType: hard "@types/yargs@npm:^17.0.8": - version: 17.0.32 - resolution: "@types/yargs@npm:17.0.32" + version: 17.0.33 + resolution: "@types/yargs@npm:17.0.33" dependencies: "@types/yargs-parser": "npm:*" - checksum: 2095e8aad8a4e66b86147415364266b8d607a3b95b4239623423efd7e29df93ba81bb862784a6e08664f645cc1981b25fd598f532019174cd3e5e1e689e1cccf + checksum: d16937d7ac30dff697801c3d6f235be2166df42e4a88bf730fa6dc09201de3727c0a9500c59a672122313341de5f24e45ee0ff579c08ce91928e519090b7906b languageName: node linkType: hard @@ -1719,6 +1929,69 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/expect@npm:2.0.5" + dependencies: + "@vitest/spy": "npm:2.0.5" + "@vitest/utils": "npm:2.0.5" + chai: "npm:^5.1.1" + tinyrainbow: "npm:^1.2.0" + checksum: 08cb1b0f106d16a5b60db733e3d436fa5eefc68571488eb570dfe4f599f214ab52e4342273b03dbe12331cc6c0cdc325ac6c94f651ad254cd62f3aa0e3d185aa + languageName: node + linkType: hard + +"@vitest/pretty-format@npm:2.0.5, @vitest/pretty-format@npm:^2.0.5": + version: 2.0.5 + resolution: "@vitest/pretty-format@npm:2.0.5" + dependencies: + tinyrainbow: "npm:^1.2.0" + checksum: 236c0798c5170a0b5ad5d4bd06118533738e820b4dd30079d8fbcb15baee949d41c60f42a9f769906c4a5ce366d7ef11279546070646c0efc03128c220c31f37 + languageName: node + linkType: hard + +"@vitest/runner@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/runner@npm:2.0.5" + dependencies: + "@vitest/utils": "npm:2.0.5" + pathe: "npm:^1.1.2" + checksum: d0ed3302a7e015bf44b7c0df9d8f7da163659e082d86f9406944b5a31a61ab9ddc1de530e06176d1f4ef0bde994b44bff4c7dab62aacdc235c8fc04b98e4a72a + languageName: node + linkType: hard + +"@vitest/snapshot@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/snapshot@npm:2.0.5" + dependencies: + "@vitest/pretty-format": "npm:2.0.5" + magic-string: "npm:^0.30.10" + pathe: "npm:^1.1.2" + checksum: 7bf38474248f5ae0aac6afad511785d2b7a023ac5158803c2868fd172b5b9c1a569fb1dd64a09a49e43fd342cab71ea485ada89b7f08d37b1622a5a0ac00271d + languageName: node + linkType: hard + +"@vitest/spy@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/spy@npm:2.0.5" + dependencies: + tinyspy: "npm:^3.0.0" + checksum: 70634c21921eb271b54d2986c21d7ab6896a31c0f4f1d266940c9bafb8ac36237846d6736638cbf18b958bd98e5261b158a6944352742accfde50b7818ff655e + languageName: node + linkType: hard + +"@vitest/utils@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/utils@npm:2.0.5" + dependencies: + "@vitest/pretty-format": "npm:2.0.5" + estree-walker: "npm:^3.0.3" + loupe: "npm:^3.1.1" + tinyrainbow: "npm:^1.2.0" + checksum: 0d1de748298f07a50281e1ba058b05dcd58da3280c14e6f016265e950bd79adab6b97822de8f0ea82d3070f585654801a9b1bcf26db4372e51cf7746bf86d73b + languageName: node + linkType: hard + "@webassemblyjs/ast@npm:1.12.1, @webassemblyjs/ast@npm:^1.12.1": version: 1.12.1 resolution: "@webassemblyjs/ast@npm:1.12.1" @@ -1950,12 +2223,12 @@ __metadata: languageName: node linkType: hard -"acorn-import-assertions@npm:^1.9.0": - version: 1.9.0 - resolution: "acorn-import-assertions@npm:1.9.0" +"acorn-import-attributes@npm:^1.9.5": + version: 1.9.5 + resolution: "acorn-import-attributes@npm:1.9.5" peerDependencies: acorn: ^8 - checksum: 3b4a194e128efdc9b86c2b1544f623aba4c1aa70d638f8ab7dc3971a5b4aa4c57bd62f99af6e5325bb5973c55863b4112e708a6f408bad7a138647ca72283afe + checksum: 5926eaaead2326d5a86f322ff1b617b0f698aa61dc719a5baa0e9d955c9885cc71febac3fb5bacff71bbf2c4f9c12db2056883c68c53eb962c048b952e1e013d languageName: node linkType: hard @@ -1969,18 +2242,20 @@ __metadata: linkType: hard "acorn-walk@npm:^8.1.1": - version: 8.3.2 - resolution: "acorn-walk@npm:8.3.2" - checksum: 7e2a8dad5480df7f872569b9dccff2f3da7e65f5353686b1d6032ab9f4ddf6e3a2cb83a9b52cf50b1497fd522154dda92f0abf7153290cc79cd14721ff121e52 + version: 8.3.3 + resolution: "acorn-walk@npm:8.3.3" + dependencies: + acorn: "npm:^8.11.0" + checksum: 4a9e24313e6a0a7b389e712ba69b66b455b4cb25988903506a8d247e7b126f02060b05a8a5b738a9284214e4ca95f383dd93443a4ba84f1af9b528305c7f243b languageName: node linkType: hard -"acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": - version: 8.11.3 - resolution: "acorn@npm:8.11.3" +"acorn@npm:^8.11.0, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": + version: 8.12.1 + resolution: "acorn@npm:8.12.1" bin: acorn: bin/acorn - checksum: 3ff155f8812e4a746fee8ecff1f227d527c4c45655bb1fad6347c3cb58e46190598217551b1500f18542d2bbe5c87120cb6927f5a074a59166fbdd9468f0a299 + checksum: 51fb26cd678f914e13287e886da2d7021f8c2bc0ccc95e03d3e0447ee278dd3b40b9c57dc222acd5881adcf26f3edc40901a4953403232129e3876793cd17386 languageName: node linkType: hard @@ -2071,14 +2346,14 @@ __metadata: linkType: hard "ajv@npm:^8.0.0, ajv@npm:^8.9.0": - version: 8.13.0 - resolution: "ajv@npm:8.13.0" + version: 8.17.1 + resolution: "ajv@npm:8.17.1" dependencies: fast-deep-equal: "npm:^3.1.3" + fast-uri: "npm:^3.0.1" json-schema-traverse: "npm:^1.0.0" require-from-string: "npm:^2.0.2" - uri-js: "npm:^4.4.1" - checksum: 14c6497b6f72843986d7344175a1aa0e2c35b1e7f7475e55bc582cddb765fca7e6bf950f465dc7846f817776d9541b706f4b5b3fbedd8dfdeb5fce6f22864264 + checksum: ec3ba10a573c6b60f94639ffc53526275917a2df6810e4ab5a6b959d87459f9ef3f00d5e7865b82677cb7d21590355b34da14d1d0b9c32d75f95a187e76fff35 languageName: node linkType: hard @@ -2226,7 +2501,7 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.7": +"array-includes@npm:^3.1.8": version: 3.1.8 resolution: "array-includes@npm:3.1.8" dependencies: @@ -2247,7 +2522,7 @@ __metadata: languageName: node linkType: hard -"array.prototype.findlastindex@npm:^1.2.3": +"array.prototype.findlastindex@npm:^1.2.5": version: 1.2.5 resolution: "array.prototype.findlastindex@npm:1.2.5" dependencies: @@ -2301,6 +2576,33 @@ __metadata: languageName: node linkType: hard +"assert@npm:^2.1.0": + version: 2.1.0 + resolution: "assert@npm:2.1.0" + dependencies: + call-bind: "npm:^1.0.2" + is-nan: "npm:^1.3.2" + object-is: "npm:^1.1.5" + object.assign: "npm:^4.1.4" + util: "npm:^0.12.5" + checksum: 7271a5da883c256a1fa690677bf1dd9d6aa882139f2bed1cd15da4f9e7459683e1da8e32a203d6cc6767e5e0f730c77a9532a87b896b4b0af0dd535f668775f0 + languageName: node + linkType: hard + +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: bbbcb117ac6480138f8c93cf7f535614282dea9dc828f540cdece85e3c665e8f78958b96afac52f29ff883c72638e6a87d469ecc9fe5bc902df03ed24a55dba8 + languageName: node + linkType: hard + +"async@npm:^3.2.3": + version: 3.2.6 + resolution: "async@npm:3.2.6" + checksum: 36484bb15ceddf07078688d95e27076379cc2f87b10c03b6dd8a83e89475a3c8df5848859dd06a4c95af1e4c16fc973de0171a77f18ea00be899aca2a4f85e70 + languageName: node + linkType: hard + "asynckit@npm:^0.4.0": version: 0.4.0 resolution: "asynckit@npm:0.4.0" @@ -2316,20 +2618,20 @@ __metadata: linkType: hard "autoprefixer@npm:^10.4.15": - version: 10.4.19 - resolution: "autoprefixer@npm:10.4.19" + version: 10.4.20 + resolution: "autoprefixer@npm:10.4.20" dependencies: - browserslist: "npm:^4.23.0" - caniuse-lite: "npm:^1.0.30001599" + browserslist: "npm:^4.23.3" + caniuse-lite: "npm:^1.0.30001646" fraction.js: "npm:^4.3.7" normalize-range: "npm:^0.1.2" - picocolors: "npm:^1.0.0" + picocolors: "npm:^1.0.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.1.0 bin: autoprefixer: bin/autoprefixer - checksum: fe0178eb8b1da4f15c6535cd329926609b22d1811e047371dccce50563623f8075dd06fb167daff059e4228da651b0bdff6d9b44281541eaf0ce0b79125bfd19 + checksum: e1f00978a26e7c5b54ab12036d8c13833fad7222828fc90914771b1263f51b28c7ddb5803049de4e77696cbd02bb25cfc3634e80533025bb26c26aacdf938940 languageName: node linkType: hard @@ -2343,13 +2645,13 @@ __metadata: linkType: hard "axios@npm:^1.6.7": - version: 1.6.8 - resolution: "axios@npm:1.6.8" + version: 1.7.7 + resolution: "axios@npm:1.7.7" dependencies: follow-redirects: "npm:^1.15.6" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 0f22da6f490335479a89878bc7d5a1419484fbb437b564a80c34888fc36759ae4f56ea28d55a191695e5ed327f0bad56e7ff60fb6770c14d1be6501505d47ab9 + checksum: 4499efc89e86b0b49ffddc018798de05fab26e3bf57913818266be73279a6418c3ce8f9e934c7d2d707ab8c095e837fc6c90608fb7715b94d357720b5f568af7 languageName: node linkType: hard @@ -2361,13 +2663,14 @@ __metadata: "@inquirer/confirm": "npm:^3.0.0" "@inquirer/input": "npm:^2.0.0" "@inquirer/select": "npm:^2.0.0" - "@playwright/test": "npm:1.42.0" + "@playwright/test": "npm:1.46.1" axios: "npm:^1.6.7" commander: "npm:^12.1.0" ora: "npm:^8.0.1" pino: "npm:^8.19.0" pino-pretty: "npm:^10.3.1" tiged: "npm:^2.12.6" + vitest: "npm:^2.0.5" bin: aztec-app: bin.js languageName: unknown @@ -2416,24 +2719,27 @@ __metadata: linkType: hard "babel-preset-current-node-syntax@npm:^1.0.0": - version: 1.0.1 - resolution: "babel-preset-current-node-syntax@npm:1.0.1" + version: 1.1.0 + resolution: "babel-preset-current-node-syntax@npm:1.1.0" dependencies: "@babel/plugin-syntax-async-generators": "npm:^7.8.4" "@babel/plugin-syntax-bigint": "npm:^7.8.3" - "@babel/plugin-syntax-class-properties": "npm:^7.8.3" - "@babel/plugin-syntax-import-meta": "npm:^7.8.3" + "@babel/plugin-syntax-class-properties": "npm:^7.12.13" + "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" + "@babel/plugin-syntax-import-attributes": "npm:^7.24.7" + "@babel/plugin-syntax-import-meta": "npm:^7.10.4" "@babel/plugin-syntax-json-strings": "npm:^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" - "@babel/plugin-syntax-numeric-separator": "npm:^7.8.3" + "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" - "@babel/plugin-syntax-top-level-await": "npm:^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" + "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.0.0 - checksum: 5ba39a3a0e6c37d25e56a4fb843be632dac98d54706d8a0933f9bcb1a07987a96d55c2b5a6c11788a74063fb2534fe68c1f1dbb6c93626850c785e0938495627 + checksum: 0b838d4412e3322cb4436f246e24e9c00bebcedfd8f00a2f51489db683bd35406bbd55a700759c28d26959c6e03f84dd6a1426f576f440267c1d7a73c5717281 languageName: node linkType: hard @@ -2456,7 +2762,7 @@ __metadata: languageName: node linkType: hard -"base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": +"base64-js@npm:^1.3.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" checksum: f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf @@ -2549,30 +2855,30 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.2, braces@npm:~3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" +"braces@npm:^3.0.3, braces@npm:~3.0.2": + version: 3.0.3 + resolution: "braces@npm:3.0.3" dependencies: - fill-range: "npm:^7.0.1" - checksum: 321b4d675791479293264019156ca322163f02dc06e3c4cab33bb15cd43d80b51efef69b0930cfde3acd63d126ebca24cd0544fa6f261e093a0fb41ab9dda381 + fill-range: "npm:^7.1.1" + checksum: 7c6dfd30c338d2997ba77500539227b9d1f85e388a5f43220865201e407e076783d0881f2d297b9f80951b4c957fcf0b51c1d2d24227631643c3f7c284b0aa04 languageName: node linkType: hard -"browserslist@npm:^4.21.10, browserslist@npm:^4.22.2, browserslist@npm:^4.23.0": - version: 4.23.0 - resolution: "browserslist@npm:4.23.0" +"browserslist@npm:^4.21.10, browserslist@npm:^4.23.1, browserslist@npm:^4.23.3": + version: 4.23.3 + resolution: "browserslist@npm:4.23.3" dependencies: - caniuse-lite: "npm:^1.0.30001587" - electron-to-chromium: "npm:^1.4.668" - node-releases: "npm:^2.0.14" - update-browserslist-db: "npm:^1.0.13" + caniuse-lite: "npm:^1.0.30001646" + electron-to-chromium: "npm:^1.5.4" + node-releases: "npm:^2.0.18" + update-browserslist-db: "npm:^1.1.0" bin: browserslist: cli.js - checksum: 8e9cc154529062128d02a7af4d8adeead83ca1df8cd9ee65a88e2161039f3d68a4d40fea7353cab6bae4c16182dec2fdd9a1cf7dc2a2935498cee1af0e998943 + checksum: 3063bfdf812815346447f4796c8f04601bf5d62003374305fd323c2a463e42776475bcc5309264e39bcf9a8605851e53560695991a623be988138b3ff8c66642 languageName: node linkType: hard -"bs-logger@npm:0.x": +"bs-logger@npm:^0.2.6": version: 0.2.6 resolution: "bs-logger@npm:0.2.6" dependencies: @@ -2621,9 +2927,16 @@ __metadata: languageName: node linkType: hard +"cac@npm:^6.7.14": + version: 6.7.14 + resolution: "cac@npm:6.7.14" + checksum: 4ee06aaa7bab8981f0d54e5f5f9d4adcd64058e9697563ce336d8a3878ed018ee18ebe5359b2430eceae87e0758e62ea2019c3f52ae6e211b1bd2e133856cd10 + languageName: node + linkType: hard + "cacache@npm:^18.0.0": - version: 18.0.2 - resolution: "cacache@npm:18.0.2" + version: 18.0.4 + resolution: "cacache@npm:18.0.4" dependencies: "@npmcli/fs": "npm:^3.1.0" fs-minipass: "npm:^3.0.0" @@ -2637,11 +2950,11 @@ __metadata: ssri: "npm:^10.0.0" tar: "npm:^6.1.11" unique-filename: "npm:^3.0.0" - checksum: 7992665305cc251a984f4fdbab1449d50e88c635bc43bf2785530c61d239c61b349e5734461baa461caaee65f040ab14e2d58e694f479c0810cffd181ba5eabc + checksum: 6c055bafed9de4f3dcc64ac3dc7dd24e863210902b7c470eb9ce55a806309b3efff78033e3d8b4f7dcc5d467f2db43c6a2857aaaf26f0094b8a351d44c42179f languageName: node linkType: hard -"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7": +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7": version: 1.0.7 resolution: "call-bind@npm:1.0.7" dependencies: @@ -2692,10 +3005,23 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001587, caniuse-lite@npm:^1.0.30001599": - version: 1.0.30001614 - resolution: "caniuse-lite@npm:1.0.30001614" - checksum: 54873ef47f5f04448f1dafe371dece0129f1f2e4644c377956e66ebfa4bfa16dd3529062b7b4d95d9e3a80129907558c19200532669c6dcd5733eff724fdf2b6 +"caniuse-lite@npm:^1.0.30001646": + version: 1.0.30001655 + resolution: "caniuse-lite@npm:1.0.30001655" + checksum: fff0c0c3ffcba89828bfa6b99f118e82c064f46f15bb8655b9f2a352a3f552ccac0b87a9fe9532f8c5a29e284aae5579791e196480ec717d11ef1d1a1c2e3ff9 + languageName: node + linkType: hard + +"chai@npm:^5.1.1": + version: 5.1.1 + resolution: "chai@npm:5.1.1" + dependencies: + assertion-error: "npm:^2.0.1" + check-error: "npm:^2.1.1" + deep-eql: "npm:^5.0.1" + loupe: "npm:^3.1.0" + pathval: "npm:^2.0.0" + checksum: e7f00e5881e3d5224f08fe63966ed6566bd9fdde175863c7c16dd5240416de9b34c4a0dd925f4fd64ad56256ca6507d32cf6131c49e1db65c62578eb31d4566c languageName: node linkType: hard @@ -2726,7 +3052,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.2": +"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -2750,6 +3076,13 @@ __metadata: languageName: node linkType: hard +"check-error@npm:^2.1.1": + version: 2.1.1 + resolution: "check-error@npm:2.1.1" + checksum: 979f13eccab306cf1785fa10941a590b4e7ea9916ea2a4f8c87f0316fc3eab07eabefb6e587424ef0f88cbcd3805791f172ea739863ca3d7ce2afc54641c7f0e + languageName: node + linkType: hard + "chokidar@npm:^3.5.3": version: 3.6.0 resolution: "chokidar@npm:3.6.0" @@ -2777,9 +3110,9 @@ __metadata: linkType: hard "chrome-trace-event@npm:^1.0.2": - version: 1.0.3 - resolution: "chrome-trace-event@npm:1.0.3" - checksum: 080ce2d20c2b9e0f8461a380e9585686caa768b1c834a464470c9dc74cda07f27611c7b727a2cd768a9cecd033297fdec4ce01f1e58b62227882c1059dec321c + version: 1.0.4 + resolution: "chrome-trace-event@npm:1.0.4" + checksum: 3058da7a5f4934b87cf6a90ef5fb68ebc5f7d06f143ed5a4650208e5d7acae47bc03ec844b29fbf5ba7e46e8daa6acecc878f7983a4f4bb7271593da91e61ff5 languageName: node linkType: hard @@ -2791,9 +3124,9 @@ __metadata: linkType: hard "cjs-module-lexer@npm:^1.0.0": - version: 1.3.1 - resolution: "cjs-module-lexer@npm:1.3.1" - checksum: cd98fbf3c7f4272fb0ebf71d08d0c54bc75ce0e30b9d186114e15b4ba791f3d310af65a339eea2a0318599af2818cdd8886d353b43dfab94468f72987397ad16 + version: 1.4.0 + resolution: "cjs-module-lexer@npm:1.4.0" + checksum: b5ef03e10297c24f0db56b13d7d2f92e377499c83d7bf9352ec73df544b5310e024dfb1779a6b810e7a06eb18caa6a0e2da5f11df8116af73306f362e67fb61a languageName: node linkType: hard @@ -2827,12 +3160,12 @@ __metadata: languageName: node linkType: hard -"cli-cursor@npm:^4.0.0": - version: 4.0.0 - resolution: "cli-cursor@npm:4.0.0" +"cli-cursor@npm:^5.0.0": + version: 5.0.0 + resolution: "cli-cursor@npm:5.0.0" dependencies: - restore-cursor: "npm:^4.0.0" - checksum: e776e8c3c6727300d0539b0d25160b2bb56aed1a63942753ba1826b012f337a6f4b7ace3548402e4f2f13b5e16bfd751be672c44b203205e7eca8be94afec42c + restore-cursor: "npm:^5.0.0" + checksum: 7ec62f69b79f6734ab209a3e4dbdc8af7422d44d360a7cb1efa8a0887bbe466a6e625650c466fe4359aee44dbe2dc0b6994b583d40a05d0808a5cb193641d220 languageName: node linkType: hard @@ -2987,13 +3320,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:^9.0.0": - version: 9.5.0 - resolution: "commander@npm:9.5.0" - checksum: 5f7784fbda2aaec39e89eb46f06a999e00224b3763dc65976e05929ec486e174fe9aac2655f03ba6a5e83875bd173be5283dc19309b7c65954701c02025b3c1d - languageName: node - linkType: hard - "compressible@npm:~2.0.16": version: 2.0.18 resolution: "compressible@npm:2.0.18" @@ -3260,15 +3586,15 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": - version: 4.3.4 - resolution: "debug@npm:4.3.4" +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5": + version: 4.3.6 + resolution: "debug@npm:4.3.6" dependencies: ms: "npm:2.1.2" peerDependenciesMeta: supports-color: optional: true - checksum: cedbec45298dd5c501d01b92b119cd3faebe5438c3917ff11ae1bff86a6c722930ac9c8659792824013168ba6db7c4668225d845c633fbdafbbf902a6389f736 + checksum: 3293416bff072389c101697d4611c402a6bacd1900ac20c0492f61a9cdd6b3b29750fc7f5e299f8058469ef60ff8fb79b86395a30374fbd2490113c1c7112285 languageName: node linkType: hard @@ -3293,6 +3619,13 @@ __metadata: languageName: node linkType: hard +"deep-eql@npm:^5.0.1": + version: 5.0.2 + resolution: "deep-eql@npm:5.0.2" + checksum: 7102cf3b7bb719c6b9c0db2e19bf0aa9318d141581befe8c7ce8ccd39af9eaa4346e5e05adef7f9bd7015da0f13a3a25dcfe306ef79dc8668aedbecb658dd247 + languageName: node + linkType: hard + "deep-extend@npm:^0.6.0": version: 0.6.0 resolution: "deep-extend@npm:0.6.0" @@ -3348,7 +3681,7 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": +"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -3522,10 +3855,21 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.668": - version: 1.4.752 - resolution: "electron-to-chromium@npm:1.4.752" - checksum: c3d577dc1d76ddf97a593f7c7c80b5be68d306064c1f81a791ce2803da6fef24e27a152e53066f36818160c04aa8018308ab12ebf71f67400ae67c2b3d044645 +"ejs@npm:^3.1.10": + version: 3.1.10 + resolution: "ejs@npm:3.1.10" + dependencies: + jake: "npm:^10.8.5" + bin: + ejs: bin/cli.js + checksum: 52eade9e68416ed04f7f92c492183340582a36482836b11eab97b159fcdcfdedc62233a1bf0bf5e5e1851c501f2dca0e2e9afd111db2599e4e7f53ee29429ae1 + languageName: node + linkType: hard + +"electron-to-chromium@npm:^1.5.4": + version: 1.5.13 + resolution: "electron-to-chromium@npm:1.5.13" + checksum: 1d88ac39447e1d718c4296f92fe89836df4688daf2d362d6c49108136795f05a56dd9c950f1c6715e0395fa037c3b5f5ea686c543fdc90e6d74a005877c45022 languageName: node linkType: hard @@ -3537,9 +3881,9 @@ __metadata: linkType: hard "emoji-regex@npm:^10.3.0": - version: 10.3.0 - resolution: "emoji-regex@npm:10.3.0" - checksum: b4838e8dcdceb44cf47f59abe352c25ff4fe7857acaf5fb51097c427f6f75b44d052eb907a7a3b86f86bc4eae3a93f5c2b7460abe79c407307e6212d65c91163 + version: 10.4.0 + resolution: "emoji-regex@npm:10.4.0" + checksum: a3fcedfc58bfcce21a05a5f36a529d81e88d602100145fcca3dc6f795e3c8acc4fc18fe773fbf9b6d6e9371205edb3afa2668ec3473fa2aa7fd47d2a9d46482d languageName: node linkType: hard @@ -3582,13 +3926,13 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.0.0, enhanced-resolve@npm:^5.12.0, enhanced-resolve@npm:^5.16.0": - version: 5.16.0 - resolution: "enhanced-resolve@npm:5.16.0" +"enhanced-resolve@npm:^5.0.0, enhanced-resolve@npm:^5.15.0, enhanced-resolve@npm:^5.17.1": + version: 5.17.1 + resolution: "enhanced-resolve@npm:5.17.1" dependencies: graceful-fs: "npm:^4.2.4" tapable: "npm:^2.2.0" - checksum: dd69669cbb638ccacefd03e04d5e195ee6a99b7f5f8012f86d2df7781834de357923e06064ea621137c4ce0b37cc12b872b4e6d1ac6ab15fe98e7f1dfbbb08c4 + checksum: 81a0515675eca17efdba2cf5bad87abc91a528fc1191aad50e275e74f045b41506167d420099022da7181c8d787170ea41e4a11a0b10b7a16f6237daecb15370 languageName: node linkType: hard @@ -3711,9 +4055,9 @@ __metadata: linkType: hard "es-module-lexer@npm:^1.2.1": - version: 1.5.2 - resolution: "es-module-lexer@npm:1.5.2" - checksum: 20b6c668691ee81781a0ae56930560c23aa28fb934fce9137820f12ae3726a25626010cbd8ed1775c217d3bae108e23dd7b805f923133dc633bfbbc2b0020524 + version: 1.5.4 + resolution: "es-module-lexer@npm:1.5.4" + checksum: 300a469488c2f22081df1e4c8398c78db92358496e639b0df7f89ac6455462aaf5d8893939087c1a1cbcbf20eed4610c70e0bcb8f3e4b0d80a5d2611c539408c languageName: node linkType: hard @@ -3757,10 +4101,90 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.21.3": + version: 0.21.5 + resolution: "esbuild@npm:0.21.5" + dependencies: + "@esbuild/aix-ppc64": "npm:0.21.5" + "@esbuild/android-arm": "npm:0.21.5" + "@esbuild/android-arm64": "npm:0.21.5" + "@esbuild/android-x64": "npm:0.21.5" + "@esbuild/darwin-arm64": "npm:0.21.5" + "@esbuild/darwin-x64": "npm:0.21.5" + "@esbuild/freebsd-arm64": "npm:0.21.5" + "@esbuild/freebsd-x64": "npm:0.21.5" + "@esbuild/linux-arm": "npm:0.21.5" + "@esbuild/linux-arm64": "npm:0.21.5" + "@esbuild/linux-ia32": "npm:0.21.5" + "@esbuild/linux-loong64": "npm:0.21.5" + "@esbuild/linux-mips64el": "npm:0.21.5" + "@esbuild/linux-ppc64": "npm:0.21.5" + "@esbuild/linux-riscv64": "npm:0.21.5" + "@esbuild/linux-s390x": "npm:0.21.5" + "@esbuild/linux-x64": "npm:0.21.5" + "@esbuild/netbsd-x64": "npm:0.21.5" + "@esbuild/openbsd-x64": "npm:0.21.5" + "@esbuild/sunos-x64": "npm:0.21.5" + "@esbuild/win32-arm64": "npm:0.21.5" + "@esbuild/win32-ia32": "npm:0.21.5" + "@esbuild/win32-x64": "npm:0.21.5" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: fa08508adf683c3f399e8a014a6382a6b65542213431e26206c0720e536b31c09b50798747c2a105a4bbba1d9767b8d3615a74c2f7bf1ddf6d836cd11eb672de + languageName: node + linkType: hard + "escalade@npm:^3.1.1, escalade@npm:^3.1.2": - version: 3.1.2 - resolution: "escalade@npm:3.1.2" - checksum: 6b4adafecd0682f3aa1cd1106b8fff30e492c7015b178bc81b2d2f75106dabea6c6d6e8508fc491bd58e597c74abb0e8e2368f943ecb9393d4162e3c2f3cf287 + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 languageName: node linkType: hard @@ -3815,68 +4239,76 @@ __metadata: linkType: hard "eslint-import-resolver-typescript@npm:^3.5.5": - version: 3.6.1 - resolution: "eslint-import-resolver-typescript@npm:3.6.1" - dependencies: - debug: "npm:^4.3.4" - enhanced-resolve: "npm:^5.12.0" - eslint-module-utils: "npm:^2.7.4" - fast-glob: "npm:^3.3.1" - get-tsconfig: "npm:^4.5.0" - is-core-module: "npm:^2.11.0" + version: 3.6.3 + resolution: "eslint-import-resolver-typescript@npm:3.6.3" + dependencies: + "@nolyfill/is-core-module": "npm:1.0.39" + debug: "npm:^4.3.5" + enhanced-resolve: "npm:^5.15.0" + eslint-module-utils: "npm:^2.8.1" + fast-glob: "npm:^3.3.2" + get-tsconfig: "npm:^4.7.5" + is-bun-module: "npm:^1.0.2" is-glob: "npm:^4.0.3" peerDependencies: eslint: "*" eslint-plugin-import: "*" - checksum: cb1cb4389916fe78bf8c8567aae2f69243dbfe624bfe21078c56ad46fa1ebf0634fa7239dd3b2055ab5c27359e4b4c28b69b11fcb3a5df8a9e6f7add8e034d86 + eslint-plugin-import-x: "*" + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + checksum: 5933b00791b7b077725b9ba9a85327d2e2dc7c8944c18a868feb317a0bf0e1e77aed2254c9c5e24dcc49360d119331d2c15281837f4269592965ace380a75111 languageName: node linkType: hard -"eslint-module-utils@npm:^2.7.4, eslint-module-utils@npm:^2.8.0": - version: 2.8.1 - resolution: "eslint-module-utils@npm:2.8.1" +"eslint-module-utils@npm:^2.8.1, eslint-module-utils@npm:^2.9.0": + version: 2.9.0 + resolution: "eslint-module-utils@npm:2.9.0" dependencies: debug: "npm:^3.2.7" peerDependenciesMeta: eslint: optional: true - checksum: 1aeeb97bf4b688d28de136ee57c824480c37691b40fa825c711a4caf85954e94b99c06ac639d7f1f6c1d69223bd21bcb991155b3e589488e958d5b83dfd0f882 + checksum: 7c45c5b54402a969e99315890c10e9bf8c8bee16c7890573343af05dfa04566d61546585678c413e5228af0550e39461be47e35a8ff0d1863e113bdbb28d1d29 languageName: node linkType: hard "eslint-plugin-import@npm:^2.27.5": - version: 2.29.1 - resolution: "eslint-plugin-import@npm:2.29.1" + version: 2.30.0 + resolution: "eslint-plugin-import@npm:2.30.0" dependencies: - array-includes: "npm:^3.1.7" - array.prototype.findlastindex: "npm:^1.2.3" + "@rtsao/scc": "npm:^1.1.0" + array-includes: "npm:^3.1.8" + array.prototype.findlastindex: "npm:^1.2.5" array.prototype.flat: "npm:^1.3.2" array.prototype.flatmap: "npm:^1.3.2" debug: "npm:^3.2.7" doctrine: "npm:^2.1.0" eslint-import-resolver-node: "npm:^0.3.9" - eslint-module-utils: "npm:^2.8.0" - hasown: "npm:^2.0.0" - is-core-module: "npm:^2.13.1" + eslint-module-utils: "npm:^2.9.0" + hasown: "npm:^2.0.2" + is-core-module: "npm:^2.15.1" is-glob: "npm:^4.0.3" minimatch: "npm:^3.1.2" - object.fromentries: "npm:^2.0.7" - object.groupby: "npm:^1.0.1" - object.values: "npm:^1.1.7" + object.fromentries: "npm:^2.0.8" + object.groupby: "npm:^1.0.3" + object.values: "npm:^1.2.0" semver: "npm:^6.3.1" tsconfig-paths: "npm:^3.15.0" peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 5f35dfbf4e8e67f741f396987de9504ad125c49f4144508a93282b4ea0127e052bde65ab6def1f31b6ace6d5d430be698333f75bdd7dca3bc14226c92a083196 + checksum: 4c9dcb1f27505c4d5dd891d2b551f56c70786d136aa3992a77e785bdc67c9f60200a2c7fb0ce55b7647fe550b12bc433d5dfa59e2c00ab44227791c5ab86badf languageName: node linkType: hard "eslint-plugin-prettier@npm:^5.0.1": - version: 5.1.3 - resolution: "eslint-plugin-prettier@npm:5.1.3" + version: 5.2.1 + resolution: "eslint-plugin-prettier@npm:5.2.1" dependencies: prettier-linter-helpers: "npm:^1.0.0" - synckit: "npm:^0.8.6" + synckit: "npm:^0.9.1" peerDependencies: "@types/eslint": ">=8.0.0" eslint: ">=8.0.0" @@ -3887,7 +4319,7 @@ __metadata: optional: true eslint-config-prettier: optional: true - checksum: f45d5fc1fcfec6b0cf038a7a65ddd10a25df4fe3f9e1f6b7f0d5100e66f046a26a2492e69ee765dddf461b93c114cf2e1eb18d4970aafa6f385448985c136e09 + checksum: 4bc8bbaf5bb556c9c501dcdff369137763c49ccaf544f9fa91400360ed5e3a3f1234ab59690e06beca5b1b7e6f6356978cdd3b02af6aba3edea2ffe69ca6e8b2 languageName: node linkType: hard @@ -3901,11 +4333,11 @@ __metadata: linkType: hard "eslint-plugin-react-refresh@npm:^0.4.3": - version: 0.4.6 - resolution: "eslint-plugin-react-refresh@npm:0.4.6" + version: 0.4.11 + resolution: "eslint-plugin-react-refresh@npm:0.4.11" peerDependencies: eslint: ">=7" - checksum: 931d5623c7c694526e9d34f61af856bb1949a0b9b9b509da29cba6c3c68fd4e1e7e36d8a340f6aecfd22329d0425c7fbb2388dd7d24b0d05218067747f5d6fe3 + checksum: 0c7d4ce30a70fbd6460ea9ca45b029b1cc806fd922d308ad332315d0e1725a37a578283809913bf7a7c84c613e3313e891dde7692a8e6ef2979dbff7edf45901 languageName: node linkType: hard @@ -4006,11 +4438,11 @@ __metadata: linkType: hard "esquery@npm:^1.4.2": - version: 1.5.0 - resolution: "esquery@npm:1.5.0" + version: 1.6.0 + resolution: "esquery@npm:1.6.0" dependencies: estraverse: "npm:^5.1.0" - checksum: a084bd049d954cc88ac69df30534043fb2aee5555b56246493f42f27d1e168f00d9e5d4192e46f10290d312dc30dc7d58994d61a609c579c1219d636996f9213 + checksum: cb9065ec605f9da7a76ca6dadb0619dfb611e37a81e318732977d90fab50a256b95fee2d925fba7c2f3f0523aa16f91587246693bc09bc34d5a59575fe6e93d2 languageName: node linkType: hard @@ -4037,6 +4469,15 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^3.0.3": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": "npm:^1.0.0" + checksum: c12e3c2b2642d2bcae7d5aa495c60fa2f299160946535763969a1c83fc74518ffa9c2cd3a8b69ac56aea547df6a8aac25f729a342992ef0bbac5f1c73e78995d + languageName: node + linkType: hard + "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -4089,6 +4530,23 @@ __metadata: languageName: node linkType: hard +"execa@npm:^8.0.1": + version: 8.0.1 + resolution: "execa@npm:8.0.1" + dependencies: + cross-spawn: "npm:^7.0.3" + get-stream: "npm:^8.0.1" + human-signals: "npm:^5.0.0" + is-stream: "npm:^3.0.0" + merge-stream: "npm:^2.0.0" + npm-run-path: "npm:^5.1.0" + onetime: "npm:^6.0.0" + signal-exit: "npm:^4.1.0" + strip-final-newline: "npm:^3.0.0" + checksum: 2c52d8775f5bf103ce8eec9c7ab3059909ba350a5164744e9947ed14a53f51687c040a250bda833f906d1283aa8803975b84e6c8f7a7c42f99dc8ef80250d1af + languageName: node + linkType: hard + "exit@npm:^0.1.2": version: 0.1.2 resolution: "exit@npm:0.1.2" @@ -4176,7 +4634,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.1": +"fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.2": version: 3.3.2 resolution: "fast-glob@npm:3.3.2" dependencies: @@ -4217,6 +4675,13 @@ __metadata: languageName: node linkType: hard +"fast-uri@npm:^3.0.1": + version: 3.0.1 + resolution: "fast-uri@npm:3.0.1" + checksum: 3cd46d6006083b14ca61ffe9a05b8eef75ef87e9574b6f68f2e17ecf4daa7aaadeff44e3f0f7a0ef4e0f7e7c20fc07beec49ff14dc72d0b500f00386592f2d10 + languageName: node + linkType: hard + "fast-url-parser@npm:1.1.3": version: 1.1.3 resolution: "fast-url-parser@npm:1.1.3" @@ -4269,12 +4734,21 @@ __metadata: languageName: node linkType: hard -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" +"filelist@npm:^1.0.4": + version: 1.0.4 + resolution: "filelist@npm:1.0.4" + dependencies: + minimatch: "npm:^5.0.1" + checksum: 426b1de3944a3d153b053f1c0ebfd02dccd0308a4f9e832ad220707a6d1f1b3c9784d6cadf6b2f68f09a57565f63ebc7bcdc913ccf8012d834f472c46e596f41 + languageName: node + linkType: hard + +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" dependencies: to-regex-range: "npm:^5.0.1" - checksum: 7cdad7d426ffbaadf45aeb5d15ec675bbd77f7597ad5399e3d2766987ed20bda24d5fac64b3ee79d93276f5865608bb22344a26b9b1ae6c4d00bd94bf611623f + checksum: b75b691bbe065472f38824f694c2f7449d7f5004aa950426a2c28f0306c60db9b880c0b0e4ed819997ffb882d1da02cfcfc819bddc94d71627f5269682edf018 languageName: node linkType: hard @@ -4360,12 +4834,12 @@ __metadata: linkType: hard "foreground-child@npm:^3.1.0": - version: 3.1.1 - resolution: "foreground-child@npm:3.1.1" + version: 3.3.0 + resolution: "foreground-child@npm:3.3.0" dependencies: cross-spawn: "npm:^7.0.0" signal-exit: "npm:^4.0.1" - checksum: 9700a0285628abaeb37007c9a4d92bd49f67210f09067638774338e146c8e9c825c5c877f072b2f75f41dc6a2d0be8664f79ffc03f6576649f54a84fb9b47de0 + checksum: 028f1d41000553fcfa6c4bb5c372963bf3d9bf0b1f25a87d1a6253014343fb69dfb1b42d9625d7cf44c8ba429940f3d0ff718b62105d4d4a4f6ef8ca0a53faa2 languageName: node linkType: hard @@ -4430,17 +4904,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^11.1.1": - version: 11.2.0 - resolution: "fs-extra@npm:11.2.0" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: d77a9a9efe60532d2e790e938c81a02c1b24904ef7a3efb3990b835514465ba720e99a6ea56fd5e2db53b4695319b644d76d5a0e9988a2beef80aa7b1da63398 - languageName: node - linkType: hard - "fs-minipass@npm:^2.0.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" @@ -4483,7 +4946,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2": +"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": version: 2.3.3 resolution: "fsevents@npm:2.3.3" dependencies: @@ -4502,7 +4965,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": +"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" dependencies: @@ -4565,6 +5028,13 @@ __metadata: languageName: node linkType: hard +"get-func-name@npm:^2.0.1": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 89830fd07623fa73429a711b9daecdb304386d237c71268007f788f113505ef1d4cc2d0b9680e072c5082490aec9df5d7758bf5ac6f1c37062855e8e3dc0b9df + languageName: node + linkType: hard + "get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": version: 1.2.4 resolution: "get-intrinsic@npm:1.2.4" @@ -4592,6 +5062,13 @@ __metadata: languageName: node linkType: hard +"get-stream@npm:^8.0.1": + version: 8.0.1 + resolution: "get-stream@npm:8.0.1" + checksum: 5c2181e98202b9dae0bb4a849979291043e5892eb40312b47f0c22b9414fc9b28a3b6063d2375705eb24abc41ecf97894d9a51f64ff021511b504477b27b4290 + languageName: node + linkType: hard + "get-symbol-description@npm:^1.0.2": version: 1.0.2 resolution: "get-symbol-description@npm:1.0.2" @@ -4603,12 +5080,12 @@ __metadata: languageName: node linkType: hard -"get-tsconfig@npm:^4.5.0": - version: 4.7.3 - resolution: "get-tsconfig@npm:4.7.3" +"get-tsconfig@npm:^4.7.5": + version: 4.8.0 + resolution: "get-tsconfig@npm:4.8.0" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: b15ca9d5d0887ebfccadc9fe88b6ff3827a5691ec90e7608a5e9c74bef959c14aba62f6bb88ac7f50322395731789a2cf654244f00e10f4f76349911b6846d6f + checksum: 943721c996d9a77351aa7c07956de77baece97f997bd30f3247f46907e4b743f7b9da02c7b3692a36f0884d3724271faeb88ed1c3aca3aba2afe3f27d6c4aeb3 languageName: node linkType: hard @@ -4638,17 +5115,18 @@ __metadata: linkType: hard "glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.3.12 - resolution: "glob@npm:10.3.12" + version: 10.4.5 + resolution: "glob@npm:10.4.5" dependencies: foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.3.6" - minimatch: "npm:^9.0.1" - minipass: "npm:^7.0.4" - path-scurry: "npm:^1.10.2" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: f60cefdc1cf3f958b2bb5823e1b233727f04916d489dc4641d76914f016e6704421e06a83cbb68b0cb1cb9382298b7a88075b844ad2127fc9727ea22b18b0711 + checksum: 19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e languageName: node linkType: hard @@ -5022,12 +5500,12 @@ __metadata: linkType: hard "https-proxy-agent@npm:^7.0.1": - version: 7.0.4 - resolution: "https-proxy-agent@npm:7.0.4" + version: 7.0.5 + resolution: "https-proxy-agent@npm:7.0.5" dependencies: agent-base: "npm:^7.0.2" debug: "npm:4" - checksum: bc4f7c38da32a5fc622450b6cb49a24ff596f9bd48dcedb52d2da3fa1c1a80e100fb506bd59b326c012f21c863c69b275c23de1a01d0b84db396822fdf25e52b + checksum: 2490e3acec397abeb88807db52cac59102d5ed758feee6df6112ab3ccd8325e8a1ce8bce6f4b66e5470eca102d31e425ace904242e4fa28dbe0c59c4bafa7b2c languageName: node linkType: hard @@ -5038,10 +5516,10 @@ __metadata: languageName: node linkType: hard -"hyperdyperid@npm:^1.2.0": - version: 1.2.0 - resolution: "hyperdyperid@npm:1.2.0" - checksum: 885ba3177c7181d315a856ee9c0005ff8eb5dcb1ce9e9d61be70987895d934d84686c37c981cceeb53216d4c9c15c1cc25f1804e84cc6a74a16993c5d7fd0893 +"human-signals@npm:^5.0.0": + version: 5.0.0 + resolution: "human-signals@npm:5.0.0" + checksum: 5a9359073fe17a8b58e5a085e9a39a950366d9f00217c4ff5878bd312e09d80f460536ea6a3f260b5943a01fe55c158d1cea3fc7bee3d0520aeef04f6d915c82 languageName: node linkType: hard @@ -5080,9 +5558,9 @@ __metadata: linkType: hard "ignore@npm:^5.2.0, ignore@npm:^5.2.4": - version: 5.3.1 - resolution: "ignore@npm:5.3.1" - checksum: 703f7f45ffb2a27fb2c5a8db0c32e7dee66b33a225d28e8db4e1be6474795f606686a6e3bcc50e1aa12f2042db4c9d4a7d60af3250511de74620fbed052ea4cd + version: 5.3.2 + resolution: "ignore@npm:5.3.2" + checksum: f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337 languageName: node linkType: hard @@ -5097,14 +5575,14 @@ __metadata: linkType: hard "import-local@npm:^3.0.2": - version: 3.1.0 - resolution: "import-local@npm:3.1.0" + version: 3.2.0 + resolution: "import-local@npm:3.2.0" dependencies: pkg-dir: "npm:^4.2.0" resolve-cwd: "npm:^3.0.0" bin: import-local-fixture: fixtures/cli.js - checksum: c67ecea72f775fe8684ca3d057e54bdb2ae28c14bf261d2607c269c18ea0da7b730924c06262eca9aed4b8ab31e31d65bc60b50e7296c85908a56e2f7d41ecd2 + checksum: 94cd6367a672b7e0cb026970c85b76902d2710a64896fa6de93bd5c571dd03b228c5759308959de205083e3b1c61e799f019c9e36ee8e9c523b993e1057f0433 languageName: node linkType: hard @@ -5244,9 +5722,18 @@ __metadata: version: 1.1.2 resolution: "is-boolean-object@npm:1.1.2" dependencies: - call-bind: "npm:^1.0.2" - has-tostringtag: "npm:^1.0.0" - checksum: 6090587f8a8a8534c0f816da868bc94f32810f08807aa72fa7e79f7e11c466d281486ffe7a788178809c2aa71fe3e700b167fe80dd96dad68026bfff8ebf39f7 + call-bind: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.0" + checksum: 6090587f8a8a8534c0f816da868bc94f32810f08807aa72fa7e79f7e11c466d281486ffe7a788178809c2aa71fe3e700b167fe80dd96dad68026bfff8ebf39f7 + languageName: node + linkType: hard + +"is-bun-module@npm:^1.0.2": + version: 1.1.0 + resolution: "is-bun-module@npm:1.1.0" + dependencies: + semver: "npm:^7.6.3" + checksum: 17cae968c3fe08e2bd66f8477e4d5a166d6299b5e7ce5c7558355551c50267f77dd386297fada6b68e4a32f01ce8920b0423e4d258242ea463b45901ec474beb languageName: node linkType: hard @@ -5257,12 +5744,12 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.11.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1": - version: 2.13.1 - resolution: "is-core-module@npm:2.13.1" +"is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1": + version: 2.15.1 + resolution: "is-core-module@npm:2.15.1" dependencies: - hasown: "npm:^2.0.0" - checksum: 2cba9903aaa52718f11c4896dabc189bab980870aae86a62dc0d5cedb546896770ee946fb14c84b7adf0735f5eaea4277243f1b95f5cefa90054f92fbcac2518 + hasown: "npm:^2.0.2" + checksum: 53432f10c69c40bfd2fa8914133a68709ff9498c86c3bf5fca3cdf3145a56fd2168cbf4a43b29843a6202a120a5f9c5ffba0a4322e1e3441739bc0b641682612 languageName: node linkType: hard @@ -5346,6 +5833,16 @@ __metadata: languageName: node linkType: hard +"is-nan@npm:^1.3.2": + version: 1.3.2 + resolution: "is-nan@npm:1.3.2" + dependencies: + call-bind: "npm:^1.0.0" + define-properties: "npm:^1.1.3" + checksum: 8bfb286f85763f9c2e28ea32e9127702fe980ffd15fa5d63ade3be7786559e6e21355d3625dd364c769c033c5aedf0a2ed3d4025d336abf1b9241e3d9eddc5b0 + languageName: node + linkType: hard + "is-negative-zero@npm:^2.0.3": version: 2.0.3 resolution: "is-negative-zero@npm:2.0.3" @@ -5425,6 +5922,13 @@ __metadata: languageName: node linkType: hard +"is-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "is-stream@npm:3.0.0" + checksum: eb2f7127af02ee9aa2a0237b730e47ac2de0d4e76a4a905a50a11557f2339df5765eaea4ceb8029f1efa978586abe776908720bfcb1900c20c6ec5145f6f29d8 + languageName: node + linkType: hard + "is-string@npm:^1.0.5, is-string@npm:^1.0.7": version: 1.0.7 resolution: "is-string@npm:1.0.7" @@ -5540,15 +6044,15 @@ __metadata: linkType: hard "istanbul-lib-instrument@npm:^6.0.0": - version: 6.0.2 - resolution: "istanbul-lib-instrument@npm:6.0.2" + version: 6.0.3 + resolution: "istanbul-lib-instrument@npm:6.0.3" dependencies: "@babel/core": "npm:^7.23.9" "@babel/parser": "npm:^7.23.9" "@istanbuljs/schema": "npm:^0.1.3" istanbul-lib-coverage: "npm:^3.2.0" semver: "npm:^7.5.4" - checksum: 405c6ac037bf8c7ee7495980b0cd5544b2c53078c10534d0c9ceeb92a9ea7dcf8510f58ccfce31336458a8fa6ccef27b570bbb602abaa8c1650f5496a807477c + checksum: a1894e060dd2a3b9f046ffdc87b44c00a35516f5e6b7baf4910369acca79e506fc5323a816f811ae23d82334b38e3ddeb8b3b331bd2c860540793b59a8689128 languageName: node linkType: hard @@ -5584,16 +6088,30 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.3.6": - version: 2.3.6 - resolution: "jackspeak@npm:2.3.6" +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" dependencies: "@isaacs/cliui": "npm:^8.0.2" "@pkgjs/parseargs": "npm:^0.11.0" dependenciesMeta: "@pkgjs/parseargs": optional: true - checksum: f01d8f972d894cd7638bc338e9ef5ddb86f7b208ce177a36d718eac96ec86638a6efa17d0221b10073e64b45edc2ce15340db9380b1f5d5c5d000cbc517dc111 + checksum: 6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 + languageName: node + linkType: hard + +"jake@npm:^10.8.5": + version: 10.9.2 + resolution: "jake@npm:10.9.2" + dependencies: + async: "npm:^3.2.3" + chalk: "npm:^4.0.2" + filelist: "npm:^1.0.4" + minimatch: "npm:^3.1.2" + bin: + jake: bin/cli.js + checksum: c4597b5ed9b6a908252feab296485a4f87cba9e26d6c20e0ca144fb69e0c40203d34a2efddb33b3d297b8bd59605e6c1f44f6221ca1e10e69175ecbf3ff5fe31 languageName: node linkType: hard @@ -6048,11 +6566,11 @@ __metadata: linkType: hard "jiti@npm:^1.20.0": - version: 1.21.0 - resolution: "jiti@npm:1.21.0" + version: 1.21.6 + resolution: "jiti@npm:1.21.6" bin: jiti: bin/jiti.js - checksum: 7f361219fe6c7a5e440d5f1dba4ab763a5538d2df8708cdc22561cf25ea3e44b837687931fca7cdd8cdd9f567300e90be989dd1321650045012d8f9ed6aab07f + checksum: 05b9ed58cd30d0c3ccd3c98209339e74f50abd9a17e716f65db46b6a35812103f6bde6e134be7124d01745586bca8cc5dae1d0d952267c3ebe55171949c32e56 languageName: node linkType: hard @@ -6201,12 +6719,12 @@ __metadata: linkType: hard "launch-editor@npm:^2.6.0": - version: 2.6.1 - resolution: "launch-editor@npm:2.6.1" + version: 2.8.2 + resolution: "launch-editor@npm:2.8.2" dependencies: picocolors: "npm:^1.0.0" shell-quote: "npm:^1.8.1" - checksum: 82d0bd9a44e7a972157719e63dac1b8196db6ec7066c1ec57a495f6c3d6e734f3c4da89549e7b33eb3b0356668ad02a9e7782b6733f5ebd7a61b7c5f635a3ee9 + checksum: 61f5465b2f4bc9fe88f29248a38e5e1c1e17eb7c85a8a2fa12f661fed5aabb9dfab2c55e4203a94c7768c2c67b5061e116cdadf54f56a9f2a3ae5beca42ea997 languageName: node linkType: hard @@ -6266,21 +6784,7 @@ __metadata: languageName: node linkType: hard -"lodash.camelcase@npm:^4.3.0": - version: 4.3.0 - resolution: "lodash.camelcase@npm:4.3.0" - checksum: fcba15d21a458076dd309fce6b1b4bf611d84a0ec252cb92447c948c533ac250b95d2e00955801ebc367e5af5ed288b996d75d37d2035260a937008e14eaf432 - languageName: node - linkType: hard - -"lodash.capitalize@npm:^4.2.1": - version: 4.2.1 - resolution: "lodash.capitalize@npm:4.2.1" - checksum: b289326497c2e24d6b8afa2af2ca4e068ef6ef007ade36bfb6f70af77ce10ea3f090eeee947d5fdcf2db4bcfa4703c8c10a5857a2b39e308bddfd1d11ad35970 - languageName: node - linkType: hard - -"lodash.memoize@npm:4.x": +"lodash.memoize@npm:^4.1.2": version: 4.1.2 resolution: "lodash.memoize@npm:4.1.2" checksum: c8713e51eccc650422716a14cece1809cfe34bc5ab5e242b7f8b4e2241c2483697b971a604252807689b9dd69bfe3a98852e19a5b89d506b000b4187a1285df8 @@ -6322,6 +6826,15 @@ __metadata: languageName: node linkType: hard +"loupe@npm:^3.1.0, loupe@npm:^3.1.1": + version: 3.1.1 + resolution: "loupe@npm:3.1.1" + dependencies: + get-func-name: "npm:^2.0.1" + checksum: 99f88badc47e894016df0c403de846fedfea61154aadabbf776c8428dd59e8d8378007135d385d737de32ae47980af07d22ba7bec5ef7beebd721de9baa0a0af + languageName: node + linkType: hard + "lower-case@npm:^2.0.2": version: 2.0.2 resolution: "lower-case@npm:2.0.2" @@ -6332,9 +6845,9 @@ __metadata: linkType: hard "lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.2.2 - resolution: "lru-cache@npm:10.2.2" - checksum: 402d31094335851220d0b00985084288136136992979d0e015f0f1697e15d1c86052d7d53ae86b614e5b058425606efffc6969a31a091085d7a2b80a8a1e26d6 + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb languageName: node linkType: hard @@ -6347,12 +6860,12 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" +"magic-string@npm:^0.30.10": + version: 0.30.11 + resolution: "magic-string@npm:0.30.11" dependencies: - yallist: "npm:^4.0.0" - checksum: cb53e582785c48187d7a188d3379c181b5ca2a9c78d2bce3e7dee36f32761d1c42983da3fe12b55cb74e1779fa94cdc2e5367c028a9b35317184ede0c07a30a9 + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + checksum: b9eb370773d0bd90ca11a848753409d8e5309b1ad56d2a1aa49d6649da710a6d2fe7237ad1a643c5a5d3800de2b9946ed9690acdfc00e6cc1aeafff3ab1752c4 languageName: node linkType: hard @@ -6365,7 +6878,7 @@ __metadata: languageName: node linkType: hard -"make-error@npm:1.x, make-error@npm:^1.1.1": +"make-error@npm:^1.1.1, make-error@npm:^1.3.6": version: 1.3.6 resolution: "make-error@npm:1.3.6" checksum: 171e458d86854c6b3fc46610cfacf0b45149ba043782558c6875d9f42f222124384ad0b468c92e996d815a8a2003817a710c0a160e49c1c394626f76fa45396f @@ -6417,18 +6930,6 @@ __metadata: languageName: node linkType: hard -"memfs@npm:^4.6.0": - version: 4.9.2 - resolution: "memfs@npm:4.9.2" - dependencies: - "@jsonjoy.com/json-pack": "npm:^1.0.3" - "@jsonjoy.com/util": "npm:^1.1.2" - sonic-forest: "npm:^1.0.0" - tslib: "npm:^2.0.0" - checksum: 2a5a2c3c2a8a70fa79e0becedc9323a620e43eef20418e128de216f586e96891cf25a51d4d37c7fdd900214de05c13749afcf2658d23a9574720759a7119c2a0 - languageName: node - linkType: hard - "merge-descriptors@npm:1.0.1": version: 1.0.1 resolution: "merge-descriptors@npm:1.0.1" @@ -6458,22 +6959,29 @@ __metadata: linkType: hard "micromatch@npm:^4.0.0, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" + version: 4.0.8 + resolution: "micromatch@npm:4.0.8" dependencies: - braces: "npm:^3.0.2" + braces: "npm:^3.0.3" picomatch: "npm:^2.3.1" - checksum: 3d6505b20f9fa804af5d8c596cb1c5e475b9b0cd05f652c5b56141cf941bd72adaeb7a436fda344235cef93a7f29b7472efc779fcdb83b478eab0867b95cdeff + checksum: 166fa6eb926b9553f32ef81f5f531d27b4ce7da60e5baf8c021d043b27a388fb95e46a8038d5045877881e673f8134122b59624d5cecbd16eb50a42e7a6b5ca8 languageName: node linkType: hard -"mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": +"mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" checksum: 0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa languageName: node linkType: hard +"mime-db@npm:>= 1.43.0 < 2": + version: 1.53.0 + resolution: "mime-db@npm:1.53.0" + checksum: 1dcc37ba8ed5d1c179f5c6f0837e8db19371d5f2ea3690c3c2f3fa8c3858f976851d3460b172b4dee78ebd606762cbb407aa398545fbacd539e519f858cd7bf4 + languageName: node + linkType: hard + "mime-db@npm:~1.33.0": version: 1.33.0 resolution: "mime-db@npm:1.33.0" @@ -6515,6 +7023,20 @@ __metadata: languageName: node linkType: hard +"mimic-fn@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-fn@npm:4.0.0" + checksum: de9cc32be9996fd941e512248338e43407f63f6d497abe8441fa33447d922e927de54d4cc3c1a3c6d652857acd770389d5a3823f311a744132760ce2be15ccbf + languageName: node + linkType: hard + +"mimic-function@npm:^5.0.0": + version: 5.0.1 + resolution: "mimic-function@npm:5.0.1" + checksum: f3d9464dd1816ecf6bdf2aec6ba32c0728022039d992f178237d8e289b48764fee4131319e72eedd4f7f094e22ded0af836c3187a7edc4595d28dd74368fd81d + languageName: node + linkType: hard + "minimalistic-assert@npm:^1.0.0": version: 1.0.1 resolution: "minimalistic-assert@npm:1.0.1" @@ -6540,12 +7062,21 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.1": - version: 9.0.4 - resolution: "minimatch@npm:9.0.4" +"minimatch@npm:^5.0.1": + version: 5.1.6 + resolution: "minimatch@npm:5.1.6" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 3defdfd230914f22a8da203747c42ee3c405c39d4d37ffda284dac5e45b7e1f6c49aa8be606509002898e73091ff2a3bbfc59c2c6c71d4660609f63aa92f98e3 + languageName: node + linkType: hard + +"minimatch@npm:^9.0.4": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" dependencies: brace-expansion: "npm:^2.0.1" - checksum: 2c16f21f50e64922864e560ff97c587d15fd491f65d92a677a344e970fe62aafdbeafe648965fa96d33c061b4d0eabfe0213466203dd793367e7f28658cf6414 + checksum: de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed languageName: node linkType: hard @@ -6566,8 +7097,8 @@ __metadata: linkType: hard "minipass-fetch@npm:^3.0.0": - version: 3.0.4 - resolution: "minipass-fetch@npm:3.0.4" + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" dependencies: encoding: "npm:^0.1.13" minipass: "npm:^7.0.3" @@ -6576,7 +7107,7 @@ __metadata: dependenciesMeta: encoding: optional: true - checksum: 1b63c1f3313e88eeac4689f1b71c9f086598db9a189400e3ee960c32ed89e06737fa23976c9305c2d57464fb3fcdc12749d3378805c9d6176f5569b0d0ee8a75 + checksum: 9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b languageName: node linkType: hard @@ -6623,10 +7154,10 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4": - version: 7.0.4 - resolution: "minipass@npm:7.0.4" - checksum: 6c7370a6dfd257bf18222da581ba89a5eaedca10e158781232a8b5542a90547540b4b9b7e7f490e4cda43acfbd12e086f0453728ecf8c19e0ef6921bc5958ac5 +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 languageName: node linkType: hard @@ -6744,8 +7275,8 @@ __metadata: linkType: hard "node-gyp@npm:latest": - version: 10.1.0 - resolution: "node-gyp@npm:10.1.0" + version: 10.2.0 + resolution: "node-gyp@npm:10.2.0" dependencies: env-paths: "npm:^2.2.0" exponential-backoff: "npm:^3.1.1" @@ -6753,13 +7284,13 @@ __metadata: graceful-fs: "npm:^4.2.6" make-fetch-happen: "npm:^13.0.0" nopt: "npm:^7.0.0" - proc-log: "npm:^3.0.0" + proc-log: "npm:^4.1.0" semver: "npm:^7.3.5" - tar: "npm:^6.1.2" + tar: "npm:^6.2.1" which: "npm:^4.0.0" bin: node-gyp: bin/node-gyp.js - checksum: 9cc821111ca244a01fb7f054db7523ab0a0cd837f665267eb962eb87695d71fb1e681f9e21464cc2fd7c05530dc4c81b810bca1a88f7d7186909b74477491a3c + checksum: 00630d67dbd09a45aee0a5d55c05e3916ca9e6d427ee4f7bc392d2d3dc5fad7449b21fc098dd38260a53d9dcc9c879b36704a1994235d4707e7271af7e9a835b languageName: node linkType: hard @@ -6770,21 +7301,21 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.14": - version: 2.0.14 - resolution: "node-releases@npm:2.0.14" - checksum: 199fc93773ae70ec9969bc6d5ac5b2bbd6eb986ed1907d751f411fef3ede0e4bfdb45ceb43711f8078bea237b6036db8b1bf208f6ff2b70c7d615afd157f3ab9 +"node-releases@npm:^2.0.18": + version: 2.0.18 + resolution: "node-releases@npm:2.0.18" + checksum: 786ac9db9d7226339e1dc84bbb42007cb054a346bd9257e6aa154d294f01bc6a6cddb1348fa099f079be6580acbb470e3c048effd5f719325abd0179e566fd27 languageName: node linkType: hard "nopt@npm:^7.0.0": - version: 7.2.0 - resolution: "nopt@npm:7.2.0" + version: 7.2.1 + resolution: "nopt@npm:7.2.1" dependencies: abbrev: "npm:^2.0.0" bin: nopt: bin/nopt.js - checksum: 9bd7198df6f16eb29ff16892c77bcf7f0cc41f9fb5c26280ac0def2cf8cf319f3b821b3af83eba0e74c85807cc430a16efe0db58fe6ae1f41e69519f585b6aff + checksum: a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 languageName: node linkType: hard @@ -6811,6 +7342,15 @@ __metadata: languageName: node linkType: hard +"npm-run-path@npm:^5.1.0": + version: 5.3.0 + resolution: "npm-run-path@npm:5.3.0" + dependencies: + path-key: "npm:^4.0.0" + checksum: 124df74820c40c2eb9a8612a254ea1d557ddfab1581c3e751f825e3e366d9f00b0d76a3c94ecd8398e7f3eee193018622677e95816e8491f0797b21e30b2deba + languageName: node + linkType: hard + "nth-check@npm:^2.0.1": version: 2.1.1 resolution: "nth-check@npm:2.1.1" @@ -6821,9 +7361,19 @@ __metadata: linkType: hard "object-inspect@npm:^1.13.1": - version: 1.13.1 - resolution: "object-inspect@npm:1.13.1" - checksum: fad603f408e345c82e946abdf4bfd774260a5ed3e5997a0b057c44153ac32c7271ff19e3a5ae39c858da683ba045ccac2f65245c12763ce4e8594f818f4a648d + version: 1.13.2 + resolution: "object-inspect@npm:1.13.2" + checksum: b97835b4c91ec37b5fd71add84f21c3f1047d1d155d00c0fcd6699516c256d4fcc6ff17a1aced873197fe447f91a3964178fd2a67a1ee2120cdaf60e81a050b4 + languageName: node + linkType: hard + +"object-is@npm:^1.1.5": + version: 1.1.6 + resolution: "object-is@npm:1.1.6" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + checksum: 506af444c4dce7f8e31f34fc549e2fb8152d6b9c4a30c6e62852badd7f520b579c679af433e7a072f9d78eb7808d230dc12e1cf58da9154dfbf8813099ea0fe0 languageName: node linkType: hard @@ -6834,7 +7384,7 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.5": +"object.assign@npm:^4.1.4, object.assign@npm:^4.1.5": version: 4.1.5 resolution: "object.assign@npm:4.1.5" dependencies: @@ -6846,7 +7396,7 @@ __metadata: languageName: node linkType: hard -"object.fromentries@npm:^2.0.7": +"object.fromentries@npm:^2.0.8": version: 2.0.8 resolution: "object.fromentries@npm:2.0.8" dependencies: @@ -6858,7 +7408,7 @@ __metadata: languageName: node linkType: hard -"object.groupby@npm:^1.0.1": +"object.groupby@npm:^1.0.3": version: 1.0.3 resolution: "object.groupby@npm:1.0.3" dependencies: @@ -6869,7 +7419,7 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.7": +"object.values@npm:^1.2.0": version: 1.2.0 resolution: "object.values@npm:1.2.0" dependencies: @@ -6919,7 +7469,7 @@ __metadata: languageName: node linkType: hard -"onetime@npm:^5.1.0, onetime@npm:^5.1.2": +"onetime@npm:^5.1.2": version: 5.1.2 resolution: "onetime@npm:5.1.2" dependencies: @@ -6928,6 +7478,24 @@ __metadata: languageName: node linkType: hard +"onetime@npm:^6.0.0": + version: 6.0.0 + resolution: "onetime@npm:6.0.0" + dependencies: + mimic-fn: "npm:^4.0.0" + checksum: 4eef7c6abfef697dd4479345a4100c382d73c149d2d56170a54a07418c50816937ad09500e1ed1e79d235989d073a9bade8557122aee24f0576ecde0f392bb6c + languageName: node + linkType: hard + +"onetime@npm:^7.0.0": + version: 7.0.0 + resolution: "onetime@npm:7.0.0" + dependencies: + mimic-function: "npm:^5.0.0" + checksum: 5cb9179d74b63f52a196a2e7037ba2b9a893245a5532d3f44360012005c9cadb60851d56716ebff18a6f47129dab7168022445df47c2aff3b276d92585ed1221 + languageName: node + linkType: hard + "open@npm:^8.0.9": version: 8.4.2 resolution: "open@npm:8.4.2" @@ -6954,19 +7522,19 @@ __metadata: linkType: hard "ora@npm:^8.0.1": - version: 8.0.1 - resolution: "ora@npm:8.0.1" + version: 8.1.0 + resolution: "ora@npm:8.1.0" dependencies: chalk: "npm:^5.3.0" - cli-cursor: "npm:^4.0.0" + cli-cursor: "npm:^5.0.0" cli-spinners: "npm:^2.9.2" is-interactive: "npm:^2.0.0" is-unicode-supported: "npm:^2.0.0" log-symbols: "npm:^6.0.0" - stdin-discarder: "npm:^0.2.1" - string-width: "npm:^7.0.0" + stdin-discarder: "npm:^0.2.2" + string-width: "npm:^7.2.0" strip-ansi: "npm:^7.1.0" - checksum: 7a94c075a7f182a6ace80c3505b945520ab16e05ebe536a714a3d61e51dd8f777c75c8be920e157e0c60ada6fe89bca37376897fb4d486bea5771229be992097 + checksum: 4ac9a6dd7fe915a354680f33ced21ee96d13d3c5ab0dc00b3c3ba9e3695ed141b1d045222990f5a71a9a91f801042a0b0d32e58dfc5509ff9b81efdd3fcf6339 languageName: node linkType: hard @@ -7032,10 +7600,10 @@ __metadata: languageName: node linkType: hard -"pako@npm:^2.1.0": - version: 2.1.0 - resolution: "pako@npm:2.1.0" - checksum: 8e8646581410654b50eb22a5dfd71159cae98145bd5086c9a7a816ec0370b5f72b4648d08674624b3870a521e6a3daffd6c2f7bc00fdefc7063c9d8232ff5116 +"package-json-from-dist@npm:^1.0.0": + version: 1.0.0 + resolution: "package-json-from-dist@npm:1.0.0" + checksum: e3ffaf6ac1040ab6082a658230c041ad14e72fabe99076a2081bb1d5d41210f11872403fc09082daf4387fc0baa6577f96c9c0e94c90c394fd57794b66aa4033 languageName: node linkType: hard @@ -7115,6 +7683,13 @@ __metadata: languageName: node linkType: hard +"path-key@npm:^4.0.0": + version: 4.0.0 + resolution: "path-key@npm:4.0.0" + checksum: 794efeef32863a65ac312f3c0b0a99f921f3e827ff63afa5cb09a377e202c262b671f7b3832a4e64731003fa94af0263713962d317b9887bd1e0c48a342efba3 + languageName: node + linkType: hard + "path-parse@npm:^1.0.7": version: 1.0.7 resolution: "path-parse@npm:1.0.7" @@ -7122,13 +7697,13 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.2": - version: 1.10.2 - resolution: "path-scurry@npm:1.10.2" +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" dependencies: lru-cache: "npm:^10.2.0" minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: d723777fbf9627f201e64656680f66ebd940957eebacf780e6cce1c2919c29c116678b2d7dbf8821b3a2caa758d125f4444005ccec886a25c8f324504e48e601 + checksum: 32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d languageName: node linkType: hard @@ -7153,10 +7728,24 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: 20a5b249e331c14479d94ec6817a182fd7a5680debae82705747b2db7ec50009a5f6648d0621c561b0572703f84dbef0858abcbd5856d3c5511426afcb1961f7 +"pathe@npm:^1.1.2": + version: 1.1.2 + resolution: "pathe@npm:1.1.2" + checksum: 64ee0a4e587fb0f208d9777a6c56e4f9050039268faaaaecd50e959ef01bf847b7872785c36483fa5cdcdbdfdb31fef2ff222684d4fc21c330ab60395c681897 + languageName: node + linkType: hard + +"pathval@npm:^2.0.0": + version: 2.0.0 + resolution: "pathval@npm:2.0.0" + checksum: 602e4ee347fba8a599115af2ccd8179836a63c925c23e04bd056d0674a64b39e3a081b643cc7bc0b84390517df2d800a46fcc5598d42c155fe4977095c2f77c5 + languageName: node + linkType: hard + +"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1": + version: 1.1.0 + resolution: "picocolors@npm:1.1.0" + checksum: 86946f6032148801ef09c051c6fb13b5cf942eaf147e30ea79edb91dd32d700934edebe782a1078ff859fb2b816792e97ef4dab03d7f0b804f6b01a0df35e023 languageName: node linkType: hard @@ -7245,27 +7834,27 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.42.0": - version: 1.42.0 - resolution: "playwright-core@npm:1.42.0" +"playwright-core@npm:1.46.1": + version: 1.46.1 + resolution: "playwright-core@npm:1.46.1" bin: playwright-core: cli.js - checksum: f08700ec743734247a0e025249ccaf1f58beb95b5c8ef6a4319f636db83ea668222967ae10299114e9f4725318f80185c7c7d97fe051ebd617acec5ae67af31a + checksum: 98e48e271caccaa6c54b3c591cbddbef36a679eef011b38e2af11fbaba0aab1f997b45f9207c4099468a0c79047a1e879bbd9e81bd880ae24501a0ee3c7a33c7 languageName: node linkType: hard -"playwright@npm:1.42.0": - version: 1.42.0 - resolution: "playwright@npm:1.42.0" +"playwright@npm:1.46.1": + version: 1.46.1 + resolution: "playwright@npm:1.46.1" dependencies: fsevents: "npm:2.3.2" - playwright-core: "npm:1.42.0" + playwright-core: "npm:1.46.1" dependenciesMeta: fsevents: optional: true bin: playwright: cli.js - checksum: 4960431c89097d7a79a24d3d4e5896cd9e4253dacfdf2891ed8a32f31c6f665a3df9af636baa23a93382733667a4d997afadb6148e6ba71f42202eeafc8968b7 + checksum: 2a328a2073313136192d74b48b981d9aeb1d4cc54926ed235f638c875f9de59c41370bb20bb2d8cf30126c52c6e25cc02db21ffafeb487c92c84c52c84846912 languageName: node linkType: hard @@ -7335,12 +7924,12 @@ __metadata: linkType: hard "postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": - version: 6.0.16 - resolution: "postcss-selector-parser@npm:6.0.16" + version: 6.1.2 + resolution: "postcss-selector-parser@npm:6.1.2" dependencies: cssesc: "npm:^3.0.0" util-deprecate: "npm:^1.0.2" - checksum: 0e11657cb3181aaf9ff67c2e59427c4df496b4a1b6a17063fae579813f80af79d444bf38f82eeb8b15b4679653fd3089e66ef0283f9aab01874d885e6cf1d2cf + checksum: 523196a6bd8cf660bdf537ad95abd79e546d54180f9afb165a4ab3e651ac705d0f8b8ce6b3164fb9e3279ce482c5f751a69eb2d3a1e8eb0fd5e82294fb3ef13e languageName: node linkType: hard @@ -7351,14 +7940,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.29, postcss@npm:^8.4.33": - version: 8.4.38 - resolution: "postcss@npm:8.4.38" +"postcss@npm:^8.4.29, postcss@npm:^8.4.33, postcss@npm:^8.4.41": + version: 8.4.44 + resolution: "postcss@npm:8.4.44" dependencies: nanoid: "npm:^3.3.7" - picocolors: "npm:^1.0.0" + picocolors: "npm:^1.0.1" source-map-js: "npm:^1.2.0" - checksum: 955407b8f70cf0c14acf35dab3615899a2a60a26718a63c848cf3c29f2467b0533991b985a2b994430d890bd7ec2b1963e36352b0774a19143b5f591540f7c06 + checksum: 53c33338261a3d4f4198f8893e9dfe8b828d8d9186142ee85f02d228f04245c5bbe31239411a357a556ad20ed96f28db24d0921d63edc428fdc9133289371a1d languageName: node linkType: hard @@ -7379,11 +7968,11 @@ __metadata: linkType: hard "prettier@npm:^3.1.1": - version: 3.2.5 - resolution: "prettier@npm:3.2.5" + version: 3.3.3 + resolution: "prettier@npm:3.3.3" bin: prettier: bin/prettier.cjs - checksum: ea327f37a7d46f2324a34ad35292af2ad4c4c3c3355da07313339d7e554320f66f65f91e856add8530157a733c6c4a897dc41b577056be5c24c40f739f5ee8c6 + checksum: b85828b08e7505716324e4245549b9205c0cacb25342a030ba8885aba2039a115dbcf75a0b7ca3b37bc9d101ee61fab8113fc69ca3359f2a226f1ecc07ad2e26 languageName: node linkType: hard @@ -7408,14 +7997,7 @@ __metadata: languageName: node linkType: hard -"proc-log@npm:^3.0.0": - version: 3.0.0 - resolution: "proc-log@npm:3.0.0" - checksum: f66430e4ff947dbb996058f6fd22de2c66612ae1a89b097744e17fb18a4e8e7a86db99eda52ccf15e53f00b63f4ec0b0911581ff2aac0355b625c8eac509b0dc - languageName: node - linkType: hard - -"proc-log@npm:^4.2.0": +"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": version: 4.2.0 resolution: "proc-log@npm:4.2.0" checksum: 17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 @@ -7854,13 +8436,13 @@ __metadata: languageName: node linkType: hard -"restore-cursor@npm:^4.0.0": - version: 4.0.0 - resolution: "restore-cursor@npm:4.0.0" +"restore-cursor@npm:^5.0.0": + version: 5.1.0 + resolution: "restore-cursor@npm:5.1.0" dependencies: - onetime: "npm:^5.1.0" - signal-exit: "npm:^3.0.2" - checksum: 6f7da8c5e422ac26aa38354870b1afac09963572cf2879443540449068cb43476e9cbccf6f8de3e0171e0d6f7f533c2bc1a0a008003c9a525bbc098e89041318 + onetime: "npm:^7.0.0" + signal-exit: "npm:^4.1.0" + checksum: c2ba89131eea791d1b25205bdfdc86699767e2b88dee2a590b1a6caa51737deac8bad0260a5ded2f7c074b7db2f3a626bcf1fcf3cdf35974cbeea5e2e6764f60 languageName: node linkType: hard @@ -7896,6 +8478,69 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.20.0": + version: 4.21.2 + resolution: "rollup@npm:4.21.2" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.21.2" + "@rollup/rollup-android-arm64": "npm:4.21.2" + "@rollup/rollup-darwin-arm64": "npm:4.21.2" + "@rollup/rollup-darwin-x64": "npm:4.21.2" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.21.2" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.21.2" + "@rollup/rollup-linux-arm64-gnu": "npm:4.21.2" + "@rollup/rollup-linux-arm64-musl": "npm:4.21.2" + "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.21.2" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.21.2" + "@rollup/rollup-linux-s390x-gnu": "npm:4.21.2" + "@rollup/rollup-linux-x64-gnu": "npm:4.21.2" + "@rollup/rollup-linux-x64-musl": "npm:4.21.2" + "@rollup/rollup-win32-arm64-msvc": "npm:4.21.2" + "@rollup/rollup-win32-ia32-msvc": "npm:4.21.2" + "@rollup/rollup-win32-x64-msvc": "npm:4.21.2" + "@types/estree": "npm:1.0.5" + fsevents: "npm:~2.3.2" + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: c9d97f7a21cde110371b2e890a31a996fee09b81e639e79372b962a9638ae653d2d24186b94632fc5dfab8a0582e1d0639dfe34b8b75051facd86915a9585a5f + languageName: node + linkType: hard + "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -7943,9 +8588,9 @@ __metadata: linkType: hard "safe-stable-stringify@npm:^2.3.1": - version: 2.4.3 - resolution: "safe-stable-stringify@npm:2.4.3" - checksum: 81dede06b8f2ae794efd868b1e281e3c9000e57b39801c6c162267eb9efda17bd7a9eafa7379e1f1cacd528d4ced7c80d7460ad26f62ada7c9e01dec61b2e768 + version: 2.5.0 + resolution: "safe-stable-stringify@npm:2.5.0" + checksum: baea14971858cadd65df23894a40588ed791769db21bafb7fd7608397dbdce9c5aac60748abae9995e0fc37e15f2061980501e012cd48859740796bea2987f49 languageName: node linkType: hard @@ -8021,14 +8666,12 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4": - version: 7.6.0 - resolution: "semver@npm:7.6.0" - dependencies: - lru-cache: "npm:^6.0.0" +"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.3": + version: 7.6.3 + resolution: "semver@npm:7.6.3" bin: semver: bin/semver.js - checksum: fbfe717094ace0aa8d6332d7ef5ce727259815bd8d8815700853f4faf23aacbd7192522f0dc5af6df52ef4fa85a355ebd2f5d39f554bd028200d6cf481ab9b53 + checksum: 88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf languageName: node linkType: hard @@ -8210,7 +8853,14 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": +"siginfo@npm:^2.0.0": + version: 2.0.0 + resolution: "siginfo@npm:2.0.0" + checksum: 3def8f8e516fbb34cb6ae415b07ccc5d9c018d85b4b8611e3dc6f8be6d1899f693a4382913c9ed51a06babb5201639d76453ab297d1c54a456544acf5c892e34 + languageName: node + linkType: hard + +"signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: 25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 @@ -8264,17 +8914,17 @@ __metadata: linkType: hard "socks-proxy-agent@npm:^8.0.3": - version: 8.0.3 - resolution: "socks-proxy-agent@npm:8.0.3" + version: 8.0.4 + resolution: "socks-proxy-agent@npm:8.0.4" dependencies: agent-base: "npm:^7.1.1" debug: "npm:^4.3.4" - socks: "npm:^2.7.1" - checksum: 4950529affd8ccd6951575e21c1b7be8531b24d924aa4df3ee32df506af34b618c4e50d261f4cc603f1bfd8d426915b7d629966c8ce45b05fb5ad8c8b9a6459d + socks: "npm:^2.8.3" + checksum: 345593bb21b95b0508e63e703c84da11549f0a2657d6b4e3ee3612c312cb3a907eac10e53b23ede3557c6601d63252103494caa306b66560f43af7b98f53957a languageName: node linkType: hard -"socks@npm:^2.7.1": +"socks@npm:^2.8.3": version: 2.8.3 resolution: "socks@npm:2.8.3" dependencies: @@ -8293,17 +8943,6 @@ __metadata: languageName: node linkType: hard -"sonic-forest@npm:^1.0.0": - version: 1.0.2 - resolution: "sonic-forest@npm:1.0.2" - dependencies: - tree-dump: "npm:^1.0.0" - peerDependencies: - tslib: 2 - checksum: d18c50eb67ccc3acf2f9677899531432cf082dbdbe4f7fab72dbaa418ebbee61472bc7c56139772d61ecf594d1606931af69a8b30ed2ff7d9cd526215b955b65 - languageName: node - linkType: hard - "source-map-js@npm:^1.2.0": version: 1.2.0 resolution: "source-map-js@npm:1.2.0" @@ -8394,11 +9033,11 @@ __metadata: linkType: hard "ssri@npm:^10.0.0": - version: 10.0.5 - resolution: "ssri@npm:10.0.5" + version: 10.0.6 + resolution: "ssri@npm:10.0.6" dependencies: minipass: "npm:^7.0.3" - checksum: b091f2ae92474183c7ac5ed3f9811457e1df23df7a7e70c9476eaa9a0c4a0c8fc190fb45acefbf023ca9ee864dd6754237a697dc52a0fb182afe65d8e77443d8 + checksum: e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 languageName: node linkType: hard @@ -8411,6 +9050,13 @@ __metadata: languageName: node linkType: hard +"stackback@npm:0.0.2": + version: 0.0.2 + resolution: "stackback@npm:0.0.2" + checksum: 89a1416668f950236dd5ac9f9a6b2588e1b9b62b1b6ad8dff1bfc5d1a15dbf0aafc9b52d2226d00c28dffff212da464eaeebfc6b7578b9d180cef3e3782c5983 + languageName: node + linkType: hard + "statuses@npm:2.0.1": version: 2.0.1 resolution: "statuses@npm:2.0.1" @@ -8425,7 +9071,14 @@ __metadata: languageName: node linkType: hard -"stdin-discarder@npm:^0.2.1": +"std-env@npm:^3.7.0": + version: 3.7.0 + resolution: "std-env@npm:3.7.0" + checksum: 60edf2d130a4feb7002974af3d5a5f3343558d1ccf8d9b9934d225c638606884db4a20d2fe6440a09605bca282af6b042ae8070a10490c0800d69e82e478f41e + languageName: node + linkType: hard + +"stdin-discarder@npm:^0.2.2": version: 0.2.2 resolution: "stdin-discarder@npm:0.2.2" checksum: c78375e82e956d7a64be6e63c809c7f058f5303efcaf62ea48350af072bacdb99c06cba39209b45a071c1acbd49116af30df1df9abb448df78a6005b72f10537 @@ -8474,14 +9127,14 @@ __metadata: languageName: node linkType: hard -"string-width@npm:^7.0.0": - version: 7.1.0 - resolution: "string-width@npm:7.1.0" +"string-width@npm:^7.2.0": + version: 7.2.0 + resolution: "string-width@npm:7.2.0" dependencies: emoji-regex: "npm:^10.3.0" get-east-asian-width: "npm:^1.0.0" strip-ansi: "npm:^7.1.0" - checksum: 68a99fbc3bd3d8eb42886ff38dce819767dee55f606f74dfa4687a07dfd21262745d9683df0aa53bf81a5dd47c13da921a501925b974bec66a7ddd634fef0634 + checksum: eb0430dd43f3199c7a46dcbf7a0b34539c76fe3aa62763d0b0655acdcbdf360b3f66f3d58ca25ba0205f42ea3491fa00f09426d3b7d3040e506878fc7664c9b9 languageName: node linkType: hard @@ -8576,6 +9229,13 @@ __metadata: languageName: node linkType: hard +"strip-final-newline@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-final-newline@npm:3.0.0" + checksum: a771a17901427bac6293fd416db7577e2bc1c34a19d38351e9d5478c3c415f523f391003b42ed475f27e33a78233035df183525395f731d3bfb8cdcbd4da08ce + languageName: node + linkType: hard + "strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -8633,13 +9293,13 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.8.6": - version: 0.8.8 - resolution: "synckit@npm:0.8.8" +"synckit@npm:^0.9.1": + version: 0.9.1 + resolution: "synckit@npm:0.9.1" dependencies: "@pkgr/core": "npm:^0.1.0" tslib: "npm:^2.6.2" - checksum: c3d3aa8e284f3f84f2f868b960c9f49239b364e35f6d20825a448449a3e9c8f49fe36cdd5196b30615682f007830d46f2ea354003954c7336723cb821e4b6519 + checksum: d8b89e1bf30ba3ffb469d8418c836ad9c0c062bf47028406b4d06548bc66af97155ea2303b96c93bf5c7c0f0d66153a6fbd6924c76521b434e6a9898982abc2e languageName: node linkType: hard @@ -8650,7 +9310,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.1.11, tar@npm:^6.1.2": +"tar@npm:^6.1.11, tar@npm:^6.2.1": version: 6.2.1 resolution: "tar@npm:6.2.1" dependencies: @@ -8687,8 +9347,8 @@ __metadata: linkType: hard "terser@npm:^5.10.0, terser@npm:^5.26.0": - version: 5.31.0 - resolution: "terser@npm:5.31.0" + version: 5.31.6 + resolution: "terser@npm:5.31.6" dependencies: "@jridgewell/source-map": "npm:^0.3.3" acorn: "npm:^8.8.2" @@ -8696,7 +9356,7 @@ __metadata: source-map-support: "npm:~0.5.20" bin: terser: bin/terser - checksum: cb127a579b03fb9dcee0d293ff24814deedcd430f447933b618e8593b7454f615b5c8493c68e86a4b0188769d5ea2af5251b5d507edb208114f7e8aebdc7c850 + checksum: b17d02b65a52a5041430572b3c514475820f5e7590fa93773c0f5b4be601ccf3f6d745bf5a79f3ee58187cf85edf61c24ddf4345783839fccb44c9c8fa9b427e languageName: node linkType: hard @@ -8718,15 +9378,6 @@ __metadata: languageName: node linkType: hard -"thingies@npm:^1.20.0": - version: 1.21.0 - resolution: "thingies@npm:1.21.0" - peerDependencies: - tslib: ^2 - checksum: 7570ee855aecb73185a672ecf3eb1c287a6512bf5476449388433b2d4debcf78100bc8bfd439b0edd38d2bc3bfb8341de5ce85b8557dec66d0f27b962c9a8bc1 - languageName: node - linkType: hard - "thread-stream@npm:^2.6.0": version: 2.7.0 resolution: "thread-stream@npm:2.7.0" @@ -8787,6 +9438,34 @@ __metadata: languageName: node linkType: hard +"tinybench@npm:^2.8.0": + version: 2.9.0 + resolution: "tinybench@npm:2.9.0" + checksum: c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c + languageName: node + linkType: hard + +"tinypool@npm:^1.0.0": + version: 1.0.1 + resolution: "tinypool@npm:1.0.1" + checksum: 90939d6a03f1519c61007bf416632dc1f0b9c1a9dd673c179ccd9e36a408437384f984fc86555a5d040d45b595abc299c3bb39d354439e98a090766b5952e73d + languageName: node + linkType: hard + +"tinyrainbow@npm:^1.2.0": + version: 1.2.0 + resolution: "tinyrainbow@npm:1.2.0" + checksum: 7f78a4b997e5ba0f5ecb75e7ed786f30bab9063716e7dff24dd84013fb338802e43d176cb21ed12480561f5649a82184cf31efb296601a29d38145b1cdb4c192 + languageName: node + linkType: hard + +"tinyspy@npm:^3.0.0": + version: 3.0.0 + resolution: "tinyspy@npm:3.0.0" + checksum: eb0dec264aa5370efd3d29743825eb115ed7f1ef8a72a431e9a75d5c9e7d67e99d04b0d61d86b8cd70c79ec27863f241ad0317bc453f78762e0cbd76d2c332d0 + languageName: node + linkType: hard + "tmpl@npm:1.0.5": version: 1.0.5 resolution: "tmpl@npm:1.0.5" @@ -8824,15 +9503,6 @@ __metadata: languageName: node linkType: hard -"tree-dump@npm:^1.0.0": - version: 1.0.1 - resolution: "tree-dump@npm:1.0.1" - peerDependencies: - tslib: 2 - checksum: 1d87a85f694089a489aa4dab21d25896ea5ab1c21e142928fc89507ab3c74a3ac21bca8d26dc102a9c16349d479be85b629233c17548178185720e4efd469126 - languageName: node - linkType: hard - "ts-api-utils@npm:^1.0.1": version: 1.3.0 resolution: "ts-api-utils@npm:1.3.0" @@ -8843,19 +9513,21 @@ __metadata: linkType: hard "ts-jest@npm:^29.1.0": - version: 29.1.2 - resolution: "ts-jest@npm:29.1.2" + version: 29.2.5 + resolution: "ts-jest@npm:29.2.5" dependencies: - bs-logger: "npm:0.x" - fast-json-stable-stringify: "npm:2.x" + bs-logger: "npm:^0.2.6" + ejs: "npm:^3.1.10" + fast-json-stable-stringify: "npm:^2.1.0" jest-util: "npm:^29.0.0" json5: "npm:^2.2.3" - lodash.memoize: "npm:4.x" - make-error: "npm:1.x" - semver: "npm:^7.5.3" - yargs-parser: "npm:^21.0.1" + lodash.memoize: "npm:^4.1.2" + make-error: "npm:^1.3.6" + semver: "npm:^7.6.3" + yargs-parser: "npm:^21.1.1" peerDependencies: "@babel/core": ">=7.0.0-beta.0 <8" + "@jest/transform": ^29.0.0 "@jest/types": ^29.0.0 babel-jest: ^29.0.0 jest: ^29.0.0 @@ -8863,6 +9535,8 @@ __metadata: peerDependenciesMeta: "@babel/core": optional: true + "@jest/transform": + optional: true "@jest/types": optional: true babel-jest: @@ -8871,7 +9545,7 @@ __metadata: optional: true bin: ts-jest: cli.js - checksum: c2f51f0241f89d127d41392decbcb83b5dfd5e57ab9d50220aa7b7e2f9b3f3b07ccdbba33311284df1c41941879e4ddfad44b15a9d0da4b74bd1b98702b729df + checksum: acb62d168faec073e64b20873b583974ba8acecdb94681164eb346cef82ade8fb481c5b979363e01a97ce4dd1e793baf64d9efd90720bc941ad7fc1c3d6f3f68 languageName: node linkType: hard @@ -8948,10 +9622,10 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.0, tslib@npm:^2.0.3, tslib@npm:^2.4.0, tslib@npm:^2.6.2": - version: 2.6.2 - resolution: "tslib@npm:2.6.2" - checksum: e03a8a4271152c8b26604ed45535954c0a45296e32445b4b87f8a5abdb2421f40b59b4ca437c4346af0f28179780d604094eb64546bee2019d903d01c6c19bdb +"tslib@npm:^2.0.0, tslib@npm:^2.0.3, tslib@npm:^2.6.2": + version: 2.7.0 + resolution: "tslib@npm:2.7.0" + checksum: 469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6 languageName: node linkType: hard @@ -9055,22 +9729,22 @@ __metadata: linkType: hard "typescript@npm:^5.0.4": - version: 5.4.5 - resolution: "typescript@npm:5.4.5" + version: 5.5.4 + resolution: "typescript@npm:5.5.4" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 2954022ada340fd3d6a9e2b8e534f65d57c92d5f3989a263754a78aba549f7e6529acc1921913560a4b816c46dce7df4a4d29f9f11a3dc0d4213bb76d043251e + checksum: 422be60f89e661eab29ac488c974b6cc0a660fb2228003b297c3d10c32c90f3bcffc1009b43876a082515a3c376b1eefcce823d6e78982e6878408b9a923199c languageName: node linkType: hard "typescript@patch:typescript@npm%3A^5.0.4#optional!builtin": - version: 5.4.5 - resolution: "typescript@patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=e012d7" + version: 5.5.4 + resolution: "typescript@patch:typescript@npm%3A5.5.4#optional!builtin::version=5.5.4&hash=e012d7" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 9cf4c053893bcf327d101b6c024a55baf05430dc30263f9adb1bf354aeffc11306fe1f23ba2f9a0209674359f16219b5b7d229e923477b94831d07d5a33a4217 + checksum: 10dd9881baba22763de859e8050d6cb6e2db854197495c6f1929b08d1eb2b2b00d0b5d9b0bcee8472f1c3f4a7ef6a5d7ebe0cfd703f853aa5ae465b8404bc1ba languageName: node linkType: hard @@ -9086,10 +9760,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~5.26.4": - version: 5.26.5 - resolution: "undici-types@npm:5.26.5" - checksum: bb673d7876c2d411b6eb6c560e0c571eef4a01c1c19925175d16e3a30c4c428181fb8d7ae802a261f283e4166a0ac435e2f505743aa9e45d893f9a3df017b501 +"undici-types@npm:~6.19.2": + version: 6.19.8 + resolution: "undici-types@npm:6.19.8" + checksum: 078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344 languageName: node linkType: hard @@ -9125,26 +9799,17 @@ __metadata: languageName: node linkType: hard -"unzipit@npm:^1.4.3": - version: 1.4.3 - resolution: "unzipit@npm:1.4.3" - dependencies: - uzip-module: "npm:^1.0.2" - checksum: 6f710615aaafb6283d5f489950e54d158deaa1c8757ba486d98ddc76f3ae3b7eab24cd24017185dd5f4edcd2df43b04431bca009538d4116c60229b60db8dd3b - languageName: node - linkType: hard - -"update-browserslist-db@npm:^1.0.13": - version: 1.0.14 - resolution: "update-browserslist-db@npm:1.0.14" +"update-browserslist-db@npm:^1.1.0": + version: 1.1.0 + resolution: "update-browserslist-db@npm:1.1.0" dependencies: escalade: "npm:^3.1.2" - picocolors: "npm:^1.0.0" + picocolors: "npm:^1.0.1" peerDependencies: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 33f787e3933cf174184a09db92ef03384e2996ee9647332b6522ba2f15014f4954c626e64f5852af788db73ce13777d92a4eacd3a08005a850a7ead5b477f0ed + checksum: a7452de47785842736fb71547651c5bbe5b4dc1e3722ccf48a704b7b34e4dcf633991eaa8e4a6a517ffb738b3252eede3773bef673ef9021baa26b056d63a5b9 languageName: node linkType: hard @@ -9158,7 +9823,7 @@ __metadata: languageName: node linkType: hard -"uri-js@npm:^4.2.2, uri-js@npm:^4.4.1": +"uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" dependencies: @@ -9210,13 +9875,6 @@ __metadata: languageName: node linkType: hard -"uzip-module@npm:^1.0.2": - version: 1.0.3 - resolution: "uzip-module@npm:1.0.3" - checksum: 206e09cf620aa178e5d8ab20425d1a4f4484de9a86673e8a5913087b7b0febb12d49a22b15574a3c5b0c9d911a0d600c9f51651de2a78ffbc6e0345b8ef3af8d - languageName: node - linkType: hard - "v8-compile-cache-lib@npm:^3.0.1": version: 3.0.1 resolution: "v8-compile-cache-lib@npm:3.0.1" @@ -9225,13 +9883,13 @@ __metadata: linkType: hard "v8-to-istanbul@npm:^9.0.1": - version: 9.2.0 - resolution: "v8-to-istanbul@npm:9.2.0" + version: 9.3.0 + resolution: "v8-to-istanbul@npm:9.3.0" dependencies: "@jridgewell/trace-mapping": "npm:^0.3.12" "@types/istanbul-lib-coverage": "npm:^2.0.1" convert-source-map: "npm:^2.0.0" - checksum: e691ba4dd0dea4a884e52c37dbda30cce6f9eeafe9b26721e449429c6bb0f4b6d1e33fabe7711d0f67f7a34c3bfd56c873f7375bba0b1534e6a2843ce99550e5 + checksum: 968bcf1c7c88c04df1ffb463c179558a2ec17aa49e49376120504958239d9e9dad5281aa05f2a78542b8557f2be0b0b4c325710262f3b838b40d703d5ed30c23 languageName: node linkType: hard @@ -9242,6 +9900,113 @@ __metadata: languageName: node linkType: hard +"vite-node@npm:2.0.5": + version: 2.0.5 + resolution: "vite-node@npm:2.0.5" + dependencies: + cac: "npm:^6.7.14" + debug: "npm:^4.3.5" + pathe: "npm:^1.1.2" + tinyrainbow: "npm:^1.2.0" + vite: "npm:^5.0.0" + bin: + vite-node: vite-node.mjs + checksum: affcc58ae8d45bce3e8bc3b5767acd57c24441634e2cd967cf97f4e5ed2bcead1714b60150cdf7ee153ebad47659c5cd419883207e1a95b69790331e3243749f + languageName: node + linkType: hard + +"vite@npm:^5.0.0": + version: 5.4.2 + resolution: "vite@npm:5.4.2" + dependencies: + esbuild: "npm:^0.21.3" + fsevents: "npm:~2.3.3" + postcss: "npm:^8.4.41" + rollup: "npm:^4.20.0" + peerDependencies: + "@types/node": ^18.0.0 || >=20.0.0 + less: "*" + lightningcss: ^1.21.0 + sass: "*" + sass-embedded: "*" + stylus: "*" + sugarss: "*" + terser: ^5.4.0 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + bin: + vite: bin/vite.js + checksum: 23e347ca8aa6f0a774227e4eb7abae228f12c6806a727b046aa75e7ee37ffc2d68cff74360e12a42c347f79adc294e2363bc723b957bf4b382b5a8fb39e4df9d + languageName: node + linkType: hard + +"vitest@npm:^2.0.5": + version: 2.0.5 + resolution: "vitest@npm:2.0.5" + dependencies: + "@ampproject/remapping": "npm:^2.3.0" + "@vitest/expect": "npm:2.0.5" + "@vitest/pretty-format": "npm:^2.0.5" + "@vitest/runner": "npm:2.0.5" + "@vitest/snapshot": "npm:2.0.5" + "@vitest/spy": "npm:2.0.5" + "@vitest/utils": "npm:2.0.5" + chai: "npm:^5.1.1" + debug: "npm:^4.3.5" + execa: "npm:^8.0.1" + magic-string: "npm:^0.30.10" + pathe: "npm:^1.1.2" + std-env: "npm:^3.7.0" + tinybench: "npm:^2.8.0" + tinypool: "npm:^1.0.0" + tinyrainbow: "npm:^1.2.0" + vite: "npm:^5.0.0" + vite-node: "npm:2.0.5" + why-is-node-running: "npm:^2.3.0" + peerDependencies: + "@edge-runtime/vm": "*" + "@types/node": ^18.0.0 || >=20.0.0 + "@vitest/browser": 2.0.5 + "@vitest/ui": 2.0.5 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@types/node": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: b4e6cca00816bf967a8589111ded72faa12f92f94ccdd0dcd0698ffcfdfc52ec662753f66b387549c600ac699b993fd952efbd99dc57fcf4d1c69a2f1022b259 + languageName: node + linkType: hard + "walker@npm:^1.0.8": version: 1.0.8 resolution: "walker@npm:1.0.8" @@ -9252,12 +10017,12 @@ __metadata: linkType: hard "watchpack@npm:^2.4.1": - version: 2.4.1 - resolution: "watchpack@npm:2.4.1" + version: 2.4.2 + resolution: "watchpack@npm:2.4.2" dependencies: glob-to-regexp: "npm:^0.4.1" graceful-fs: "npm:^4.1.2" - checksum: c694de0a61004e587a8a0fdc9cfec20ee692c52032d9ab2c2e99969a37fdab9e6e1bd3164ed506f9a13f7c83e65563d563e0d6b87358470cdb7309b83db78683 + checksum: ec60a5f0e9efaeca0102fd9126346b3b2d523e01c34030d3fddf5813a7125765121ebdc2552981136dcd2c852deb1af0b39340f2fcc235f292db5399d0283577 languageName: node linkType: hard @@ -9383,19 +10148,18 @@ __metadata: linkType: hard "webpack@npm:^5.88.2, webpack@npm:^5.90.1": - version: 5.91.0 - resolution: "webpack@npm:5.91.0" + version: 5.94.0 + resolution: "webpack@npm:5.94.0" dependencies: - "@types/eslint-scope": "npm:^3.7.3" "@types/estree": "npm:^1.0.5" "@webassemblyjs/ast": "npm:^1.12.1" "@webassemblyjs/wasm-edit": "npm:^1.12.1" "@webassemblyjs/wasm-parser": "npm:^1.12.1" acorn: "npm:^8.7.1" - acorn-import-assertions: "npm:^1.9.0" + acorn-import-attributes: "npm:^1.9.5" browserslist: "npm:^4.21.10" chrome-trace-event: "npm:^1.0.2" - enhanced-resolve: "npm:^5.16.0" + enhanced-resolve: "npm:^5.17.1" es-module-lexer: "npm:^1.2.1" eslint-scope: "npm:5.1.1" events: "npm:^3.2.0" @@ -9415,7 +10179,7 @@ __metadata: optional: true bin: webpack: bin/webpack.js - checksum: 74a3e0ea1c9a492accf035317f31769ffeaaab415811524b9f17bc7bf7012c5b6e1a9860df5ca6903f3ae2618727b801eb47d9351a2595dfffb25941d368b88c + checksum: b4d1b751f634079bd177a89eef84d80fa5bb8d6fc15d72ab40fc2b9ca5167a79b56585e1a849e9e27e259803ee5c4365cb719e54af70a43c06358ec268ff4ebf languageName: node linkType: hard @@ -9485,6 +10249,18 @@ __metadata: languageName: node linkType: hard +"why-is-node-running@npm:^2.3.0": + version: 2.3.0 + resolution: "why-is-node-running@npm:2.3.0" + dependencies: + siginfo: "npm:^2.0.0" + stackback: "npm:0.0.2" + bin: + why-is-node-running: cli.js + checksum: 1cde0b01b827d2cf4cb11db962f3958b9175d5d9e7ac7361d1a7b0e2dc6069a263e69118bd974c4f6d0a890ef4eedfe34cf3d5167ec14203dbc9a18620537054 + languageName: node + linkType: hard + "widest-line@npm:^4.0.1": version: 4.0.1 resolution: "widest-line@npm:4.0.1" @@ -9559,8 +10335,8 @@ __metadata: linkType: hard "ws@npm:^8.13.0": - version: 8.17.0 - resolution: "ws@npm:8.17.0" + version: 8.18.0 + resolution: "ws@npm:8.18.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -9569,7 +10345,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 55241ec93a66fdfc4bf4f8bc66c8eb038fda2c7a4ee8f6f157f2ca7dc7aa76aea0c0da0bf3adb2af390074a70a0e45456a2eaf80e581e630b75df10a64b0a990 + checksum: 25eb33aff17edcb90721ed6b0eb250976328533ad3cd1a28a274bd263682e7296a6591ff1436d6cbc50fa67463158b062f9d1122013b361cec99a05f84680e06 languageName: node linkType: hard @@ -9594,7 +10370,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^21.0.1, yargs-parser@npm:^21.1.1": +"yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" checksum: f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 @@ -9630,6 +10406,13 @@ __metadata: languageName: node linkType: hard +"yoctocolors-cjs@npm:^2.1.2": + version: 2.1.2 + resolution: "yoctocolors-cjs@npm:2.1.2" + checksum: a0e36eb88fea2c7981eab22d1ba45e15d8d268626e6c4143305e2c1628fa17ebfaa40cd306161a8ce04c0a60ee0262058eab12567493d5eb1409780853454c6f + languageName: node + linkType: hard + "yup@npm:^1.2.0": version: 1.4.0 resolution: "yup@npm:1.4.0" diff --git a/docs/docs/aztec/concepts/circuits/index.md b/docs/docs/aztec/concepts/circuits/index.md index aad4f994459..9e6272b37e4 100644 --- a/docs/docs/aztec/concepts/circuits/index.md +++ b/docs/docs/aztec/concepts/circuits/index.md @@ -22,7 +22,7 @@ This page focusses on the core protocol circuits. These circuits check that the When a function in an Ethereum smart contract is executed, the EVM performs checks to ensure that Ethereum's transaction rules are being adhered-to correctly. Stuff like: - "Does this tx have a valid signature?" -- "Does this contract address contain deployed code? +- "Does this contract address contain deployed code?" - "Does this function exist in the requested contract?" - "Is this function allowed to call this function?" - "How much gas has been paid, and how much is left?" diff --git a/docs/docs/aztec/concepts/storage/partial_notes.md b/docs/docs/aztec/concepts/storage/partial_notes.md index 2ea605e50df..7a72ef21814 100644 --- a/docs/docs/aztec/concepts/storage/partial_notes.md +++ b/docs/docs/aztec/concepts/storage/partial_notes.md @@ -10,7 +10,7 @@ Partial notes are a concept that allows users to commit to an encrypted value, a Why is this useful? -Consider the case where a user wants to pay for a transaction fee, using a [fee-payment contract](../../../protocol-specs/gas-and-fees/index.md) and they want to do this privately. They can't be certain what the transaction fee will be because the state of the network will have progressed by the time the transaction is processed by the sequencer, and transaction fees are dynamic. So the user can commit to a value for the transaction fee, publicly post this commitment, the fee payer can update the public commitment, deducting the final cost of the transaction from the commitment and returning the unused value to the user. +Consider the case where a user wants to pay for a transaction fee, using a [fee-payment contract](../../../protocol-specs/gas-and-fees/index.md) and they want to do this privately. They can't be certain what the transaction fee will be because the state of the network will have progressed by the time the transaction is processed by the sequencer, and transaction fees are dynamic. So the user can commit to a value for the transaction fee, publicly post this commitment, the fee payer (aka paymaster) can update the public commitment, deducting the final cost of the transaction from the commitment and returning the unused value to the user. So, in general, the user is: @@ -18,7 +18,7 @@ So, in general, the user is: - encrypting/compressing that computation with a point - passing that point as an argument to a public function -And the fee payer is: +And the paymaster is: - updating that point in public - treating/emitting the result(s) as a note hash(es) @@ -32,6 +32,20 @@ To do this, we leverage the following properties of elliptic curve operations: Property 1 allows us to be continually adding to a point on elliptic curve and property 2 allows us to pass the point to a public realm without revealing anything about the point preimage. +### DEXes + +Currently private swaps require 2 transactions. One to start the swap and another to claim the swapped token from the DEX. With partial notes, you can create a note with zero value for the received amount and have another party complete it later from a public function, with the final swapped amount. This reduces the number of transactions needed to swap privately. + +Comparing to the flow above, the user is doing some private computation to stage the swap, encrypting the computation with a point and passing the point as an argument to a public function. Then another party is updating that point in public and emitting the result as a note hash for the user doing the swap. + +### Lending + +A similar pattern can be used for a lending protocol. The user can deposit a certain amount of a token to the lending contract and create a partial note for the borrowed token that will be completed by another party. This reduces the number of required transactions from 2 to 1. + +### Private Refunds + +Private transaction refunds from paymasters are the original inspiration for partial notes. Without partial notes, you have to claim your refund note. But the act of claiming itself needs gas! What if you overpaid fees on the refund tx? Then you have another 2nd order refund that you need to claim. This creates a never ending cycle! Partial notes allow paymasters to refund users without the user needing to claim the refund. + Before getting to partial notes let's recap what is the flow of standard notes. ## Note lifecycle recap diff --git a/docs/docs/guides/developer_guides/getting_started/quickstart.md b/docs/docs/guides/developer_guides/getting_started/quickstart.md index edf15edd5ea..6ec66163c11 100644 --- a/docs/docs/guides/developer_guides/getting_started/quickstart.md +++ b/docs/docs/guides/developer_guides/getting_started/quickstart.md @@ -20,7 +20,7 @@ You need two global dependencies in your machine: Run: ```bash -bash -i <(curl -s install.aztec.network) +bash -i <(curl -s https://install.aztec.network) ``` This will install the following tools: @@ -73,6 +73,13 @@ To update the sandbox, you can just run: aztec-up ``` +## Clone a Box (optional) + +You can use the `npx aztec-app` command to clone a ready-to-go "aztec box" with a sample contract or frontend. Assuming you have [node](https://nodejs.org/en/) installed, run: + +```bash +npx aztec-app +``` ## Install Noir LSP (recommended) diff --git a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md index 1a8a31e971a..5841e5eb3fc 100644 --- a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md +++ b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md @@ -9,20 +9,34 @@ tags: [accounts, keys] ## Introduction -It is possible for users to rotate their keys, which can be helpful if some of their keys are leaked. +It is possible for users to rotate their keys, which can be helpful if some of their keys are leaked. Key rotation allows users to continue using the same account without having to create a new one. -Because of this, notes are associated with their `nullifier key` rather than any sort of 'owner' address. +Because of this, notes are often associated with their `nullifier key` (through a nullifier public key hash, often called `npk_m_hash`) rather than any sort of 'owner' address. It is still possible to nullify the notes with the old nullifier key even after the key rotation. +## `TokenNote` example + +See the structure of the `TokenNote` below: + +#include_code TokenNote noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr rust + +In the `TokenNote` type, you can see that the nullifer computation gets the nullifier secret key specific to the contract from the PXE, based on the stored `npk_m_hash`, so a `TokenNote` is not inherently or permanently linked to a specific Aztec account. + +#include_code nullifier noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr rust + ## Things to consider -- 'Owner' is arbitrary - as long as you know the nullifier secret, you can nullify a note -- Consider how key rotation can affect account contracts, eg you can add additional security checks for who or how the key rotation is called +- When using the `npk_m_hash`, used to represent ownership, whoever has the nullifier secret can nullify a note. +- Consider how key rotation can affect account contracts, e.g. you can add additional security checks for who or how the key rotation is called + +## Resources + +- End to end tests for key rotation can be found [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/end-to-end/src/e2e_key_rotation.test.ts) ## Glossary - `npk_m_hash`: master nullifying public key hash - `nsk_app`: app nullifying secret key - the app-specific NSK (learn more about app-scoped keys [here](../../../../../aztec/concepts/accounts/keys.md#scoped-keys)) - `nsk_hash`: nullifying secret key hash -- `ivpk_m`: incoming view public key (master) (learn more about IVPKs [here](../../../../../aztec/concepts/accounts/keys.md#incoming-viewing-keys)) \ No newline at end of file +- `ivpk_m`: incoming view public key (master) (learn more about IVPKs [here](../../../../../aztec/concepts/accounts/keys.md#incoming-viewing-keys)) diff --git a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/how_to_emit_event.md b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/how_to_emit_event.md index 97918ab49b5..0c0c7fc9d33 100644 --- a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/how_to_emit_event.md +++ b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/how_to_emit_event.md @@ -54,14 +54,7 @@ Aztec.nr enables smart contract developers to design custom notes, meaning devel ## Unencrypted Events -Unencrypted events are events which can be read by anyone. -They can be emitted by both public and private functions. - -:::danger - -- Emitting unencrypted events from private function is a significant privacy leak and it should be considered by the developer whether it is acceptable. - -::: +Unencrypted events are events which can be read by anyone. They can be emitted **only** by public functions. ### Call emit_unencrypted_log diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index fe66cc1505e..c21a171a4fe 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -6,7 +6,43 @@ keywords: [sandbox, aztec, notes, migration, updating, upgrading] Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them. -## TBD +## 0.53.0 +### [Aztec.nr] Remove `OwnedNote` and create `UintNote` +`OwnedNote` allowed having a U128 `value` in the custom note while `ValueNote` restricted to just a Field. + +We have removed `OwnedNote` but are introducing a more genric `UintNote` within aztec.nr +``` +#[aztec(note)] +struct UintNote { + // The integer stored by the note + value: U128, + // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. + npk_m_hash: Field, + // Randomness of the note to hide its contents + randomness: Field, +} +``` + +### [TXE] logging +You can now use `debug_log()` within your contract to print logs when using the TXE + +Remember to set the following environment variables to activate debug logging: +```bash +export DEBUG="aztec:*" +export LOG_LEVEL="debug" +``` + +### [Account] no assert in is_valid_impl + +`is_valid_impl` method in account contract asserted if signature was true. Instead now we will return the verification to give flexibility to developers to handle it as they please. + +```diff +- let verification = std::ecdsa_secp256k1::verify_signature(public_key.x, public_key.y, signature, hashed_message); +- assert(verification == true); +- true ++ std::ecdsa_secp256k1::verify_signature(public_key.x, public_key.y, signature, hashed_message) + +## 0.49.0 ### Key Rotation API overhaul @@ -823,7 +859,7 @@ This change was made to communicate that we do not constrain the value in circui Historically it have been possible to "view" `unconstrained` functions to simulate them and get the return values, but not for `public` nor `private` functions. This has lead to a lot of bad code where we have the same function implemented thrice, once in `private`, once in `public` and once in `unconstrained`. It is not possible to call `simulate` on any call to get the return values! -However, beware that it currently always returns a Field array of size 4 for private and public. +However, beware that it currently always returns a Field array of size 4 for private and public. This will change to become similar to the return values of the `unconstrained` functions with proper return types. ```diff diff --git a/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx b/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx index a59bee534e5..8e97a5ce0a8 100644 --- a/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx +++ b/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx @@ -207,14 +207,6 @@ Click on an instruction name to jump to its section. 0x18 - \[\`COINBASE\`\](#isa-section-coinbase) - (UNIMPLEMENTED) Get the block's beneficiary address - { - `M[dstOffset] = context.environment.globals.coinbase` - } - - - 0x19 \[\`FEEPERL2GAS\`\](#isa-section-feeperl2gas) Get the fee to be paid per "L2 gas" - constant for entire transaction { @@ -222,7 +214,7 @@ Click on an instruction name to jump to its section. } - 0x1a + 0x19 \[\`FEEPERDAGAS\`\](#isa-section-feeperdagas) Get the fee to be paid per "DA gas" - constant for entire transaction { @@ -230,23 +222,7 @@ Click on an instruction name to jump to its section. } - 0x1b - \[\`BLOCKL2GASLIMIT\`\](#isa-section-blockl2gaslimit) - (UNIMPLEMENTED) Total amount of "L2 gas" that a block can consume - { - `M[dstOffset] = context.environment.globals.l2GasLimit` - } - - - 0x1c - \[\`BLOCKDAGASLIMIT\`\](#isa-section-blockdagaslimit) - (UNIMPLEMENTED) Total amount of "DA gas" that a block can consume - { - `M[dstOffset] = context.environment.globals.daGasLimit` - } - - - 0x1d + 0x1a \[\`CALLDATACOPY\`\](#isa-section-calldatacopy) Copy calldata into memory { @@ -254,7 +230,7 @@ Click on an instruction name to jump to its section. } - 0x1e + 0x1b \[\`L2GASLEFT\`\](#isa-section-l2gasleft) Remaining "L2 gas" for this call (after this instruction) { @@ -262,7 +238,7 @@ Click on an instruction name to jump to its section. } - 0x1f + 0x1c \[\`DAGASLEFT\`\](#isa-section-dagasleft) Remaining "DA gas" for this call (after this instruction) { @@ -270,7 +246,7 @@ Click on an instruction name to jump to its section. } - 0x20 + 0x1d \[\`JUMP\`\](#isa-section-jump) Jump to a location in the bytecode { @@ -278,7 +254,7 @@ Click on an instruction name to jump to its section. } - 0x21 + 0x1e \[\`JUMPI\`\](#isa-section-jumpi) Conditionally jump to a location in the bytecode { @@ -286,7 +262,7 @@ Click on an instruction name to jump to its section. } - 0x22 + 0x1f \[\`INTERNALCALL\`\](#isa-section-internalcall) Make an internal call. Push the current PC to the internal call stack and jump to the target location. @@ -295,7 +271,7 @@ context.machineState.pc = loc`} - 0x23 + 0x20 \[\`INTERNALRETURN\`\](#isa-section-internalreturn) Return from an internal call. Pop from the internal call stack and jump to the popped location. { @@ -303,7 +279,7 @@ context.machineState.pc = loc`} } - 0x24 + 0x21 \[\`SET\`\](#isa-section-set) Set a memory word from a constant in the bytecode { @@ -311,7 +287,7 @@ context.machineState.pc = loc`} } - 0x25 + 0x22 \[\`MOV\`\](#isa-section-mov) Move a word from source memory location to destination { @@ -319,7 +295,7 @@ context.machineState.pc = loc`} } - 0x26 + 0x23 \[\`CMOV\`\](#isa-section-cmov) Move a word (conditionally chosen) from one memory location to another (`d = cond > 0 ? a : b`) { @@ -327,7 +303,7 @@ context.machineState.pc = loc`} } - 0x27 + 0x24 \[\`SLOAD\`\](#isa-section-sload) Load a word from this contract's persistent public storage. Zero is loaded for unwritten slots. @@ -335,7 +311,7 @@ context.machineState.pc = loc`} - 0x28 + 0x25 \[\`SSTORE\`\](#isa-section-sstore) Write a word to this contract's persistent public storage @@ -343,7 +319,7 @@ context.machineState.pc = loc`} - 0x29 + 0x26 \[\`NOTEHASHEXISTS\`\](#isa-section-notehashexists) Check whether a note hash exists in the note hash tree (as of the start of the current block) @@ -355,7 +331,7 @@ M[existsOffset] = exists`} - 0x2a + 0x27 \[\`EMITNOTEHASH\`\](#isa-section-emitnotehash) Emit a new note hash to be inserted into the note hash tree @@ -365,7 +341,7 @@ M[existsOffset] = exists`} - 0x2b + 0x28 \[\`NULLIFIEREXISTS\`\](#isa-section-nullifierexists) Check whether a nullifier exists in the nullifier tree (including nullifiers from earlier in the current transaction or from earlier in the current block) @@ -376,7 +352,7 @@ M[existsOffset] = exists`} - 0x2c + 0x29 \[\`EMITNULLIFIER\`\](#isa-section-emitnullifier) Emit a new nullifier to be inserted into the nullifier tree @@ -386,7 +362,7 @@ M[existsOffset] = exists`} - 0x2d + 0x2a \[\`L1TOL2MSGEXISTS\`\](#isa-section-l1tol2msgexists) Check if a message exists in the L1-to-L2 message tree @@ -397,7 +373,7 @@ M[existsOffset] = exists`} - 0x2e + 0x2b \[\`GETCONTRACTINSTANCE\`\](#isa-section-getcontractinstance) Copies contract instance data to memory @@ -413,7 +389,7 @@ M[existsOffset] = exists`} - 0x2f + 0x2c \[\`EMITUNENCRYPTEDLOG\`\](#isa-section-emitunencryptedlog) Emit an unencrypted log @@ -426,7 +402,7 @@ M[existsOffset] = exists`} - 0x30 + 0x2d \[\`SENDL2TOL1MSG\`\](#isa-section-sendl2tol1msg) Send an L2-to-L1 message @@ -440,7 +416,7 @@ M[existsOffset] = exists`} - 0x31 + 0x2e \[\`CALL\`\](#isa-section-call) Call into another contract @@ -455,7 +431,7 @@ updateContextAfterNestedCall(context, instr.args, nestedContext)`} - 0x32 + 0x2f \[\`STATICCALL\`\](#isa-section-staticcall) Call into another contract, disallowing World State and Accrued Substate modifications @@ -470,7 +446,7 @@ updateContextAfterNestedCall(context, instr.args, nestedContext)`} - 0x33 + 0x30 \[\`DELEGATECALL\`\](#isa-section-delegatecall) (UNIMPLEMENTED) Call into another contract, but keep the caller's `sender` and `storageAddress` @@ -485,7 +461,7 @@ updateContextAfterNestedCall(context, instr.args, nestedContext)`} - 0x34 + 0x31 \[\`RETURN\`\](#isa-section-return) Halt execution within this context (without revert), optionally returning some data @@ -494,7 +470,7 @@ halt`} - 0x35 + 0x32 \[\`REVERT\`\](#isa-section-revert) Halt execution within this context as `reverted`, optionally returning some data @@ -504,7 +480,7 @@ halt`} - 0x36 + 0x33 \[\`TORADIXLE\`\](#isa-section-to_radix_le) Convert a word to an array of limbs in little-endian radix form TBD: Storage of limbs and if T[dstOffset] is constrained to U8 @@ -981,29 +957,12 @@ Get this L2 block's timestamp [![](/img/protocol-specs/public-vm/bit-formats/TIMESTAMP.png)](/img/protocol-specs/public-vm/bit-formats/TIMESTAMP.png) -### `COINBASE` -(UNIMPLEMENTED) Get the block's beneficiary address - -[See in table.](#isa-table-coinbase) - -- **Opcode**: 0x18 -- **Category**: Execution Environment - Globals -- **Flags**: - - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. -- **Args**: - - **dstOffset**: memory offset specifying where to store operation's result -- **Expression**: `M[dstOffset] = context.environment.globals.coinbase` -- **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 56 - -[![](/img/protocol-specs/public-vm/bit-formats/COINBASE.png)](/img/protocol-specs/public-vm/bit-formats/COINBASE.png) - ### `FEEPERL2GAS` Get the fee to be paid per "L2 gas" - constant for entire transaction [See in table.](#isa-table-feeperl2gas) -- **Opcode**: 0x19 +- **Opcode**: 0x18 - **Category**: Execution Environment - Globals - Gas - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1020,7 +979,7 @@ Get the fee to be paid per "DA gas" - constant for entire transaction [See in table.](#isa-table-feeperdagas) -- **Opcode**: 0x1a +- **Opcode**: 0x19 - **Category**: Execution Environment - Globals - Gas - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1032,46 +991,12 @@ Get the fee to be paid per "DA gas" - constant for entire transaction [![](/img/protocol-specs/public-vm/bit-formats/FEEPERDAGAS.png)](/img/protocol-specs/public-vm/bit-formats/FEEPERDAGAS.png) -### `BLOCKL2GASLIMIT` -(UNIMPLEMENTED) Total amount of "L2 gas" that a block can consume - -[See in table.](#isa-table-blockl2gaslimit) - -- **Opcode**: 0x1b -- **Category**: Execution Environment - Globals -- **Flags**: - - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. -- **Args**: - - **dstOffset**: memory offset specifying where to store operation's result -- **Expression**: `M[dstOffset] = context.environment.globals.l2GasLimit` -- **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 56 - -[![](/img/protocol-specs/public-vm/bit-formats/BLOCKL2GASLIMIT.png)](/img/protocol-specs/public-vm/bit-formats/BLOCKL2GASLIMIT.png) - -### `BLOCKDAGASLIMIT` -(UNIMPLEMENTED) Total amount of "DA gas" that a block can consume - -[See in table.](#isa-table-blockdagaslimit) - -- **Opcode**: 0x1c -- **Category**: Execution Environment - Globals -- **Flags**: - - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. -- **Args**: - - **dstOffset**: memory offset specifying where to store operation's result -- **Expression**: `M[dstOffset] = context.environment.globals.daGasLimit` -- **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 56 - -[![](/img/protocol-specs/public-vm/bit-formats/BLOCKDAGASLIMIT.png)](/img/protocol-specs/public-vm/bit-formats/BLOCKDAGASLIMIT.png) - ### `CALLDATACOPY` Copy calldata into memory [See in table.](#isa-table-calldatacopy) -- **Opcode**: 0x1d +- **Opcode**: 0x1a - **Category**: Execution Environment - Calldata - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1091,7 +1016,7 @@ Remaining "L2 gas" for this call (after this instruction) [See in table.](#isa-table-l2gasleft) -- **Opcode**: 0x1e +- **Opcode**: 0x1b - **Category**: Machine State - Gas - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1108,7 +1033,7 @@ Remaining "DA gas" for this call (after this instruction) [See in table.](#isa-table-dagasleft) -- **Opcode**: 0x1f +- **Opcode**: 0x1c - **Category**: Machine State - Gas - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1125,7 +1050,7 @@ Jump to a location in the bytecode [See in table.](#isa-table-jump) -- **Opcode**: 0x20 +- **Opcode**: 0x1d - **Category**: Machine State - Control Flow - **Args**: - **loc**: target location to jump to @@ -1140,7 +1065,7 @@ Conditionally jump to a location in the bytecode [See in table.](#isa-table-jumpi) -- **Opcode**: 0x21 +- **Opcode**: 0x1e - **Category**: Machine State - Control Flow - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1158,7 +1083,7 @@ Make an internal call. Push the current PC to the internal call stack and jump t [See in table.](#isa-table-internalcall) -- **Opcode**: 0x22 +- **Opcode**: 0x1f - **Category**: Machine State - Control Flow - **Args**: - **loc**: target location to jump/call to @@ -1176,7 +1101,7 @@ Return from an internal call. Pop from the internal call stack and jump to the p [See in table.](#isa-table-internalreturn) -- **Opcode**: 0x23 +- **Opcode**: 0x20 - **Category**: Machine State - Control Flow - **Expression**: `context.machineState.pc = context.machineState.internalCallStack.pop()` - **Bit-size**: 16 @@ -1188,7 +1113,7 @@ Set a memory word from a constant in the bytecode [See in table.](#isa-table-set) -- **Opcode**: 0x24 +- **Opcode**: 0x21 - **Category**: Machine State - Memory - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1208,7 +1133,7 @@ Move a word from source memory location to destination [See in table.](#isa-table-mov) -- **Opcode**: 0x25 +- **Opcode**: 0x22 - **Category**: Machine State - Memory - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1226,7 +1151,7 @@ Move a word (conditionally chosen) from one memory location to another (`d \= co [See in table.](#isa-table-cmov) -- **Opcode**: 0x26 +- **Opcode**: 0x23 - **Category**: Machine State - Memory - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1247,7 +1172,7 @@ Load a word from this contract's persistent public storage. Zero is loaded for u [See in table.](#isa-table-sload) -- **Opcode**: 0x27 +- **Opcode**: 0x24 - **Category**: World State - Public Storage - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1292,7 +1217,7 @@ Write a word to this contract's persistent public storage [See in table.](#isa-table-sstore) -- **Opcode**: 0x28 +- **Opcode**: 0x25 - **Category**: World State - Public Storage - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1332,7 +1257,7 @@ Check whether a note hash exists in the note hash tree (as of the start of the c [See in table.](#isa-table-notehashexists) -- **Opcode**: 0x29 +- **Opcode**: 0x26 - **Category**: World State - Notes & Nullifiers - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1370,7 +1295,7 @@ Emit a new note hash to be inserted into the note hash tree [See in table.](#isa-table-emitnotehash) -- **Opcode**: 0x2a +- **Opcode**: 0x27 - **Category**: World State - Notes & Nullifiers - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1402,7 +1327,7 @@ Check whether a nullifier exists in the nullifier tree (including nullifiers fro [See in table.](#isa-table-nullifierexists) -- **Opcode**: 0x2b +- **Opcode**: 0x28 - **Category**: World State - Notes & Nullifiers - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1439,7 +1364,7 @@ Emit a new nullifier to be inserted into the nullifier tree [See in table.](#isa-table-emitnullifier) -- **Opcode**: 0x2c +- **Opcode**: 0x29 - **Category**: World State - Notes & Nullifiers - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1471,7 +1396,7 @@ Check if a message exists in the L1-to-L2 message tree [See in table.](#isa-table-l1tol2msgexists) -- **Opcode**: 0x2d +- **Opcode**: 0x2a - **Category**: World State - Messaging - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1510,7 +1435,7 @@ Copies contract instance data to memory [See in table.](#isa-table-getcontractinstance) -- **Opcode**: 0x2e +- **Opcode**: 0x2b - **Category**: Other - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1540,7 +1465,7 @@ Emit an unencrypted log [See in table.](#isa-table-emitunencryptedlog) -- **Opcode**: 0x2f +- **Opcode**: 0x2c - **Category**: Accrued Substate - Logging - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1565,7 +1490,7 @@ Send an L2-to-L1 message [See in table.](#isa-table-sendl2tol1msg) -- **Opcode**: 0x30 +- **Opcode**: 0x2d - **Category**: Accrued Substate - Messaging - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1591,7 +1516,7 @@ Call into another contract [See in table.](#isa-table-call) -- **Opcode**: 0x31 +- **Opcode**: 0x2e - **Category**: Control Flow - Contract Calls - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1638,7 +1563,7 @@ Call into another contract, disallowing World State and Accrued Substate modific [See in table.](#isa-table-staticcall) -- **Opcode**: 0x32 +- **Opcode**: 0x2f - **Category**: Control Flow - Contract Calls - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1682,7 +1607,7 @@ T[retOffset:retOffset+retSize] = field`} [See in table.](#isa-table-delegatecall) -- **Opcode**: 0x33 +- **Opcode**: 0x30 - **Category**: Control Flow - Contract Calls - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1726,7 +1651,7 @@ Halt execution within this context (without revert), optionally returning some d [See in table.](#isa-table-return) -- **Opcode**: 0x34 +- **Opcode**: 0x31 - **Category**: Control Flow - Contract Calls - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1748,7 +1673,7 @@ Halt execution within this context as `reverted`, optionally returning some data [See in table.](#isa-table-revert) -- **Opcode**: 0x35 +- **Opcode**: 0x32 - **Category**: Control Flow - Contract Calls - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1771,7 +1696,7 @@ Convert a word to an array of limbs in little-endian radix form [See in table.](#isa-table-to_radix_le) -- **Opcode**: 0x36 +- **Opcode**: 0x33 - **Category**: Conversions - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. diff --git a/docs/src/preprocess/InstructionSet/InstructionSet.js b/docs/src/preprocess/InstructionSet/InstructionSet.js index 1dab654b9fd..be0a6c174ca 100644 --- a/docs/src/preprocess/InstructionSet/InstructionSet.js +++ b/docs/src/preprocess/InstructionSet/InstructionSet.js @@ -658,24 +658,6 @@ const INSTRUCTION_SET_RAW = [ "Tag checks": "", "Tag updates": "`T[dstOffset] = u64`", }, - { - id: "coinbase", - Name: "`COINBASE`", - Category: "Execution Environment - Globals", - Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], - Args: [ - { - name: "dstOffset", - description: - "memory offset specifying where to store operation's result", - }, - ], - Expression: "`M[dstOffset] = context.environment.globals.coinbase`", - Summary: "(UNIMPLEMENTED) Get the block's beneficiary address", - Details: "", - "Tag checks": "", - "Tag updates": "`T[dstOffset] = field`", - }, { id: "feeperl2gas", Name: "`FEEPERL2GAS`", @@ -714,42 +696,6 @@ const INSTRUCTION_SET_RAW = [ "Tag checks": "", "Tag updates": "`T[dstOffset] = field`", }, - { - id: "blockl2gaslimit", - Name: "`BLOCKL2GASLIMIT`", - Category: "Execution Environment - Globals", - Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], - Args: [ - { - name: "dstOffset", - description: - "memory offset specifying where to store operation's result", - }, - ], - Expression: "`M[dstOffset] = context.environment.globals.l2GasLimit`", - Summary: '(UNIMPLEMENTED) Total amount of "L2 gas" that a block can consume', - Details: "", - "Tag checks": "", - "Tag updates": "`T[dstOffset] = field`", - }, - { - id: "blockdagaslimit", - Name: "`BLOCKDAGASLIMIT`", - Category: "Execution Environment - Globals", - Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], - Args: [ - { - name: "dstOffset", - description: - "memory offset specifying where to store operation's result", - }, - ], - Expression: "`M[dstOffset] = context.environment.globals.daGasLimit`", - Summary: '(UNIMPLEMENTED) Total amount of "DA gas" that a block can consume', - Details: "", - "Tag checks": "", - "Tag updates": "`T[dstOffset] = field`", - }, { id: "calldatacopy", Name: "`CALLDATACOPY`", diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index c8bcd862df5..82933e08a27 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -102,7 +102,7 @@ library Constants { uint256 internal constant INITIAL_L2_BLOCK_NUM = 1; uint256 internal constant BLOB_SIZE_IN_BYTES = 126976; uint256 internal constant ETHEREUM_SLOT_DURATION = 12; - uint256 internal constant AZTEC_SLOT_DURATION = 12; + uint256 internal constant AZTEC_SLOT_DURATION = 36; uint256 internal constant AZTEC_EPOCH_DURATION = 48; uint256 internal constant AZTEC_TARGET_COMMITTEE_SIZE = 48; uint256 internal constant GENESIS_ARCHIVE_ROOT = diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index 07f8afdcbe3..f62fe416457 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x0f24dbb7e2a507326574582c3f44c08266eb441e926f2d68ca112f358585669f", + "archive": "0x2e45afa261e3aac1f5afe60c9c839d54feafeb03a1fa1676265cb50fd7144202", "body": "0x00000000", "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6", "decodedHeader": { @@ -20,12 +20,12 @@ }, "globalVariables": { "blockNumber": 1, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000033", + "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000031", "chainId": 31337, - "timestamp": 1724861610, + "timestamp": 1725365629, "version": 1, - "coinbase": "0x872bd7c2a38898f9fc254b86f0fd95475f7eec20", - "feeRecipient": "0x2d78818b03bcaf7034fca9d658f1212c6b2aecd6839e03cc21e2846fc061202d", + "coinbase": "0xe18d2e77cb7d56929128e82138140e07f81237f0", + "feeRecipient": "0x249d3ad6f4117aa61fb1c3f901889be704af87fc9bb1686ba21218a3b50c36bf", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -56,8 +56,8 @@ } } }, - "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000100b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000008019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000066cf4caa872bd7c2a38898f9fc254b86f0fd95475f7eec202d78818b03bcaf7034fca9d658f1212c6b2aecd6839e03cc21e2846fc061202d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00a46e722d885c3bf479f8cf2a786adfde7a8c43740214163f7f9846914cbe6f", + "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000100b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000008019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000066d6fd7de18d2e77cb7d56929128e82138140e07f81237f0249d3ad6f4117aa61fb1c3f901889be704af87fc9bb1686ba21218a3b50c36bf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0042736ccfe5affa7d43b08218d225ef79539cf41495e3db480aedf4ec65d918", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_2.json b/l1-contracts/test/fixtures/empty_block_2.json index 76c3b241250..895b1f906d3 100644 --- a/l1-contracts/test/fixtures/empty_block_2.json +++ b/l1-contracts/test/fixtures/empty_block_2.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x25126f40ad58d24006e6db629c2efb1e0868a50d5c21aa342894137b2b08bc0b", + "archive": "0x002edae6c81b7fcd630fd745c8e6fa957b8d4ac97b55baa072fae18f4a94b14e", "body": "0x00000000", "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6", "decodedHeader": { @@ -20,12 +20,12 @@ }, "globalVariables": { "blockNumber": 2, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000035", + "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000032", "chainId": 31337, - "timestamp": 1724861634, + "timestamp": 1725365665, "version": 1, - "coinbase": "0x872bd7c2a38898f9fc254b86f0fd95475f7eec20", - "feeRecipient": "0x2d78818b03bcaf7034fca9d658f1212c6b2aecd6839e03cc21e2846fc061202d", + "coinbase": "0xe18d2e77cb7d56929128e82138140e07f81237f0", + "feeRecipient": "0x249d3ad6f4117aa61fb1c3f901889be704af87fc9bb1686ba21218a3b50c36bf", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -33,7 +33,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x0f24dbb7e2a507326574582c3f44c08266eb441e926f2d68ca112f358585669f" + "root": "0x2e45afa261e3aac1f5afe60c9c839d54feafeb03a1fa1676265cb50fd7144202" }, "stateReference": { "l1ToL2MessageTree": { @@ -56,8 +56,8 @@ } } }, - "header": "0x0f24dbb7e2a507326574582c3f44c08266eb441e926f2d68ca112f358585669f00000002000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000200b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000010019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000066cf4cc2872bd7c2a38898f9fc254b86f0fd95475f7eec202d78818b03bcaf7034fca9d658f1212c6b2aecd6839e03cc21e2846fc061202d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00de3870b035eca1a73e8adf24b738db855a034548805b300d8dbecfd2a6e66b", + "header": "0x2e45afa261e3aac1f5afe60c9c839d54feafeb03a1fa1676265cb50fd714420200000002000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000200b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000010019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000066d6fda1e18d2e77cb7d56929128e82138140e07f81237f0249d3ad6f4117aa61fb1c3f901889be704af87fc9bb1686ba21218a3b50c36bf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00b9a5096ad3d9edef7e78a242b1402a5cd1adeb08ee654c6e738a08b3522483", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_1.json b/l1-contracts/test/fixtures/mixed_block_1.json index b38d3363fc4..ca70a23d40d 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -58,7 +58,7 @@ ] }, "block": { - "archive": "0x1c4782ca647f1ed559bce9f625bfae6a561ce96481c49d9b31ce4df8f46124b1", + "archive": "0x216b15f092c571bf4e72deff46dbfc36e706d0dae56313d6dde566c42c2c706c", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e0800c47667396742a5474f325e2567bff3bb99b7f0bfd2b1a689b635d8b8726cce00284120278895e8d47084ae759f390e9634881e41369a257a36fe99a2369dc800a328b4a4a6ed156325253b4ab2af7ca00e21caf7963f0fba8a88ccdc3512c300705c99df420bface231f6855799db1d0ed7d39419abc47aa8c6efe2ae7aae2009299cc308de6d23788384411e024791a5b2448e455fbdd1d1f28f3ff76631f002d6c03d81ad764de51b0f34584645191cdc2aaae2ca08fb838d142b95d62f5003032f3618b2df0fa335d5fd548d6d85e42b4e7eb5fff9eb687facbbdecb8a60016cab7ddf4d1b440d53d10284c5c82a78b2d4e27dcdb44ef434ef4c6bad6783f0000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000561000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005660000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000056700000000000000000000000000000000000000000000000000000000000005710000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000057200000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000576000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000577000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000571000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000572000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000057f00000000000000000000000000000000000000000000000000000000000005760000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000057700000000000000000000000000000000000000000000000000000000000005810000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000586000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000587000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be0800789ff73d7787206612d96dfc2143f2344de21669a3f8cae7fe9a8918631eb00084a17f00bf8793b6851a106e9155543125e0be987ad3c8334456bdda171d0b00a400f8fd336ad84f467465964008238fd1b7f9c51c22912d706cd2b874d24e002c79bdd83c14ff50a46964f838ee207564909e28af79a57fc195810d36f9b20070083c6ef1e4dd88a064e94d2582283b203cf8a2ab1667f4370eda1b4c1fe8005373dffb5b590053d7762efcf9e11280f1486ce82e7996d94ee0f5d7c093bc009eefd90eb40e79c78bac1f71ec78bdc2f8b30041974239bdc765edffed813800ea95742e72792ca7a0f66ce9f55bc47dc09d5ea08c1b9018763102776978303f0000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005a100000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005a200000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005a300000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005a400000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005a500000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005a600000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005a700000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005a800000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005bf00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0800a68d2df6e48c8b31f4c76529e586de2cd9d0f2f2fdfbc4c523db9e3a29e9b80016c236e57bf17afe324437acd1060772e3f31d4f9e734ad758d0627c4ba2a200d659011ddde95e32886bdd8c9464da1ca144ccadd539f0992b4abb491d812a00c8025bb9006a976ebd6ad940155f15f89ca0bb7312b53841fc257e7ed689c8004165f2c46b70fb183468b38f31bba7aa9d22ce8dfb61fe721470729ce1c6b100afeb60dd983514ebbaee141b2196f3eb3c9c299f576a0097872cc85a79a43f005f6bfee53d20a474901493558419dbceb3aca40e5e18915d38031498f4d2bb008791217ee341ec5dc11f7d7a31160fb1b1f2cf767062970e9526e5751956253f00000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005f600000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005f700000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005f800000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005f900000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005fa00000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005fb00000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005fc00000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005fd00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005fe00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ff00000000000000000000000000000000000000000000000000000000000005f6000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005f7000000000000000000000000000000000000000000000000000000000000060100000000000000000000000000000000000000000000000000000000000005f8000000000000000000000000000000000000000000000000000000000000060200000000000000000000000000000000000000000000000000000000000005f9000000000000000000000000000000000000000000000000000000000000060300000000000000000000000000000000000000000000000000000000000005fa000000000000000000000000000000000000000000000000000000000000060400000000000000000000000000000000000000000000000000000000000005fb000000000000000000000000000000000000000000000000000000000000060500000000000000000000000000000000000000000000000000000000000005fc000000000000000000000000000000000000000000000000000000000000060600000000000000000000000000000000000000000000000000000000000005fd000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000005fe0000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e0800c064a9343bfaf1345a5ad188e96aa4c5bad0b4a5590da51a9ff8f3c98ade8d008803d57dd0923c95a01b2bfbee4df6d66dc7baee1d2cd2770575feb86d040200ea64eed9489feb7bdf29bf817a6e8772e549da7b291028852d0dd3810cee9500947e8f904d41be8a4e08b146b4e1f0cd88f55722ef987d1d485c4196ab9f71002e5d9ed5d71bc3bea6edf988c4b9ba7fceb0815180d893852ed343c64ab55c0040f7f519ec89d360d83e242b6c0ce049d2b3356b8cfbf1ff3b733ef0f8a089006f5cfe5fc4a7b87c634f9e253a7cea2052229250d0c0e913eb50b5ef3612de00b759fce0eed36bb653b67255cce111b3529c383bd7d2b758f8cb53a4451f273f0000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000621000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000622000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006260000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062700000000000000000000000000000000000000000000000000000000000006310000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000063200000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000636000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000637000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000631000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000632000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000063f00000000000000000000000000000000000000000000000000000000000006360000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000063700000000000000000000000000000000000000000000000000000000000006410000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000064200000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000646000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000647000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x00e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b", "decodedHeader": { @@ -70,12 +70,12 @@ }, "globalVariables": { "blockNumber": 1, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000043", + "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000036", "chainId": 31337, - "timestamp": 1724860686, + "timestamp": 1725363553, "version": 1, - "coinbase": "0x9ca40d2eb00ca73819f826b0a788dd9891e21d13", - "feeRecipient": "0x07803e414075315a9195dd8f9ef9154cc40db0c0a4cb08aa98e253635741c0f2", + "coinbase": "0x8b4e0a203a4cb152c773e772e885992eae96c1f5", + "feeRecipient": "0x2e8dcd300baa8f3802239585fb4b2cd9e80da86f6107dff3c3214ae9098937d2", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -106,8 +106,8 @@ } } }, - "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000400e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00d0169cc64b8f1bd695ec8611a5602da48854dc4cc04989c4b63288b339cb1814f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000101a995cda6f326074cf650c6644269e29dbd0532e6a832238345b53ee70c878af000001000deac8396e31bc1196b442ad724bf8f751a245e518147d738cc84b9e1a56b4420000018023866f4c16f3ea1f37dd2ca42d1a635ea909b6c016e45e8434780d3741eb7dbb000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000066cf490e9ca40d2eb00ca73819f826b0a788dd9891e21d1307803e414075315a9195dd8f9ef9154cc40db0c0a4cb08aa98e253635741c0f2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x004c32b99c2c2cfac2f922454f3b7dd86ee2c8c34c98369b5b6f78a4703ae74f", + "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000400e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00d0169cc64b8f1bd695ec8611a5602da48854dc4cc04989c4b63288b339cb1814f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000101a995cda6f326074cf650c6644269e29dbd0532e6a832238345b53ee70c878af000001000deac8396e31bc1196b442ad724bf8f751a245e518147d738cc84b9e1a56b4420000018023866f4c16f3ea1f37dd2ca42d1a635ea909b6c016e45e8434780d3741eb7dbb000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000066d6f5618b4e0a203a4cb152c773e772e885992eae96c1f52e8dcd300baa8f3802239585fb4b2cd9e80da86f6107dff3c3214ae9098937d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0071c722ed49fb32154c380d246094e2bd6a10c9e0d9f779b00fe3e812a8f553", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_2.json b/l1-contracts/test/fixtures/mixed_block_2.json index 8b58730d955..5f657e3cb5e 100644 --- a/l1-contracts/test/fixtures/mixed_block_2.json +++ b/l1-contracts/test/fixtures/mixed_block_2.json @@ -58,7 +58,7 @@ ] }, "block": { - "archive": "0x1ae32d8b8b3e677d02908a8922a6d03d2ee72021039bf6a6e0fbea570b8f7b47", + "archive": "0x10c574d7d51855bc971ce1dc2dfb7266e5ac050d424022ea4d36b883e8a53886", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e08003bbb1177505f3433bb062787fcac6585d30fa1a7e0b809ca5eef1cecc56cd0002d5b86280022d106b72e4425ea49f927ca2b8138fc13b3d9feeaf36ae61fb100adab9d66b73ae23a6e9127ebe0bcd963ef4312dd66878a6be131d39a7ee01c00d48f30dbb82c96c734c8abe33f4f9f75e6d0ba4462ee07d73c5335e04a02e900f31a3a4e7333ac6043a929fca12f5347e9e8bf1d67f5993860a774f10b77bc00230e3132bfa5df23e2e018b20cd4e0c75555825ee7924da73f017a279d39cd0095e2affd6b67c6ecbf77fa1e638139498e1642abb468c58ca8ce275260ea6100362e0941035fd171fab926caf55d18b22f7de99d60ac6f454386a9cce4a1ff3f0000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000661000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000662000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006660000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000066700000000000000000000000000000000000000000000000000000000000006710000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000067200000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000676000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000677000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000671000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000672000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000067f00000000000000000000000000000000000000000000000000000000000006760000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000067700000000000000000000000000000000000000000000000000000000000006810000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000068200000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000686000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000687000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be08004a32502b5d2a0cf5d776c92ef74de61a28e7882bdadeb3b0530f472704604300808c2412e2725ecaa6a6bd77e3159349e238dc7817f906ba32afd40b3cb3cb00d7d4e3b313c4cce9bd98c317ea715847a92d795b82a6f8b8144b7c61bee64200b76f07678c289f41378029b1353a73e1afbe241612a97c23e7fc059099f49d00c72046b39a9dc902cee36db5214c72315636bd824abfabdf80b1c5e6a01fd7006e0a74fec166a12f5a62954776784f01cba3be7ab876eef2e49a2ab7a5b0f900c83ddd8f6b91086bc83485adbe8056212b4d33b91840cd3dc649f9736881460022441e76225010acce7f429dc754fb3260ae1d387937978f69c67a879ed0733f0000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006a100000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006a200000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006a300000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006a400000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006a500000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006a600000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006a700000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006a800000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006bf00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0800bb07f923e24c36227d717557d58d32b99370b81f7a70d1835becc1114f7d7700624291eff6ab801e5668bc6619a3df132f8b392b063f09dfe8a69e38224eb200bd6b195f8716ab3dc93c44037cac579d25d0e77c2782b5aa62534ee25d36bc008c99d470d2c53624a8c5bedfeffdcc5356f6da89ee0e372b3ea3fa4f8cd652009944e00a3f9a7d2e8a535d3a210c3271d5732518037704d67ef5d42a8b82c200523014cb6eabe4366c6e599ba96534fc15ecc804a13fbaaacf8717e1b0a8d20005621252c4b36c113f21ad6c13b99e5cef514bdd98ef0aae4075b5cb5a000a00d80cb2a60aae6c3d2e7d27fb1519a708a18bb5b5085f78684bdee7512856a93f00000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006f600000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006f700000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006f800000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006f900000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006fa00000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006fb00000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006fc00000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006fd00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006fe00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ff00000000000000000000000000000000000000000000000000000000000006f6000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000006f7000000000000000000000000000000000000000000000000000000000000070100000000000000000000000000000000000000000000000000000000000006f8000000000000000000000000000000000000000000000000000000000000070200000000000000000000000000000000000000000000000000000000000006f9000000000000000000000000000000000000000000000000000000000000070300000000000000000000000000000000000000000000000000000000000006fa000000000000000000000000000000000000000000000000000000000000070400000000000000000000000000000000000000000000000000000000000006fb000000000000000000000000000000000000000000000000000000000000070500000000000000000000000000000000000000000000000000000000000006fc000000000000000000000000000000000000000000000000000000000000070600000000000000000000000000000000000000000000000000000000000006fd000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000006fe0000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e0800a38df4d53fe5da3d48c97dd0f58e7a52faade40c8f50bc0f6408a2b5b3829800a3d4b994758c6630518cce3116391874b9b3b8a1bbcb36485d2702f05af359004c06e9dd14418667d7c66384699665f9222ed08be87c67293a2f1b6b4c41aa006b77b11703f0e3d21aa68c9f6d2ae8ad94ecafdb56be0c4605a0c6723e9ddc0049a087e215b640d8360f8dd98e07c77e4d2025a0dcdcaf78bc00bd6fde09680014741a52013a10622de90b1a7854f1203af5c97121a4b3774c249fba6e0dba00c783bd01c4a4cafe83fd3b4d1ce0c555be4b6d1f772cccccf86049f9af0bbe002ff3ac4d7e2f1caf1fb30e1d20eba5be2b6a42dd54690dee988a934026491e3f0000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000721000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000722000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007260000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000072700000000000000000000000000000000000000000000000000000000000007310000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000073200000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000736000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000737000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000731000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000732000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000073f00000000000000000000000000000000000000000000000000000000000007360000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000073700000000000000000000000000000000000000000000000000000000000007410000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000074200000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000743000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000744000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000745000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000746000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000747000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000748000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd646", "decodedHeader": { @@ -70,12 +70,12 @@ }, "globalVariables": { "blockNumber": 2, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000055", + "slotNumber": "0x000000000000000000000000000000000000000000000000000000000000003c", "chainId": 31337, - "timestamp": 1724860902, + "timestamp": 1725363769, "version": 1, - "coinbase": "0x9ca40d2eb00ca73819f826b0a788dd9891e21d13", - "feeRecipient": "0x07803e414075315a9195dd8f9ef9154cc40db0c0a4cb08aa98e253635741c0f2", + "coinbase": "0x8b4e0a203a4cb152c773e772e885992eae96c1f5", + "feeRecipient": "0x2e8dcd300baa8f3802239585fb4b2cd9e80da86f6107dff3c3214ae9098937d2", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -83,7 +83,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x1c4782ca647f1ed559bce9f625bfae6a561ce96481c49d9b31ce4df8f46124b1" + "root": "0x216b15f092c571bf4e72deff46dbfc36e706d0dae56313d6dde566c42c2c706c" }, "stateReference": { "l1ToL2MessageTree": { @@ -106,8 +106,8 @@ } } }, - "header": "0x1c4782ca647f1ed559bce9f625bfae6a561ce96481c49d9b31ce4df8f46124b1000000020000000000000000000000000000000000000000000000000000000000000004008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd64600212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700d4b436f0c9857646ed7cf0836bd61c857183956d1acefe52fc99ef7b333a38224c43ed89fb9404e06e7382170d1e279a53211bab61876f38d8a4180390b7ad0000002017752a4346cf34b18277458ace73be4895316cb1c3cbce628d573d5d10cde7ce00000200152db065a479b5630768d6c5250bb6233e71729f857c16cffa98569acf90a2bf000002800a020b31737a919cbd6b0c0fe25d466a11e2186eb8038cd63a5e7d2900473d53000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000066cf49e69ca40d2eb00ca73819f826b0a788dd9891e21d1307803e414075315a9195dd8f9ef9154cc40db0c0a4cb08aa98e253635741c0f2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00450d818debc92707ef43bd43269cfe23681e8eb7485ce97cac5fe88c08bb91", + "header": "0x216b15f092c571bf4e72deff46dbfc36e706d0dae56313d6dde566c42c2c706c000000020000000000000000000000000000000000000000000000000000000000000004008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd64600212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700d4b436f0c9857646ed7cf0836bd61c857183956d1acefe52fc99ef7b333a38224c43ed89fb9404e06e7382170d1e279a53211bab61876f38d8a4180390b7ad0000002017752a4346cf34b18277458ace73be4895316cb1c3cbce628d573d5d10cde7ce00000200152db065a479b5630768d6c5250bb6233e71729f857c16cffa98569acf90a2bf000002800a020b31737a919cbd6b0c0fe25d466a11e2186eb8038cd63a5e7d2900473d53000002800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000066d6f6398b4e0a203a4cb152c773e772e885992eae96c1f52e8dcd300baa8f3802239585fb4b2cd9e80da86f6107dff3c3214ae9098937d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0036cc7f0dc092d6e6a05eeb3482ec901a4631d4ae504a5aa41cb465e0bf7f4c", "numTxs": 4 } } \ No newline at end of file diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index bd79ab30bae..f74333b068b 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/aztec-nr branch = master - commit = 52c0befb2bcd0e704c150cd71aa4bae366782136 + commit = dc3dd6c2fd00a84d21d567f11bcff2dfae13f982 method = merge cmdver = 0.4.6 - parent = 5abe573bebf9d2c3e0cd8db1b8c060fff980105f + parent = a091055a34d7c87500caa1b77189d43efee84aca diff --git a/noir-projects/aztec-nr/Nargo.toml b/noir-projects/aztec-nr/Nargo.toml index 8f2ac888ccf..f4185b088a6 100644 --- a/noir-projects/aztec-nr/Nargo.toml +++ b/noir-projects/aztec-nr/Nargo.toml @@ -6,4 +6,5 @@ members = [ "compressed-string", "easy-private-state", "value-note", + "uint-note", ] diff --git a/noir-projects/aztec-nr/authwit/src/auth.nr b/noir-projects/aztec-nr/authwit/src/auth.nr index 9e240682fae..a533bd589b5 100644 --- a/noir-projects/aztec-nr/authwit/src/auth.nr +++ b/noir-projects/aztec-nr/authwit/src/auth.nr @@ -215,7 +215,11 @@ pub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf * @param on_behalf_of The address that have authorized the current call * @param inner_hash The hash of the message to authorize */ -pub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) { +pub fn assert_inner_hash_valid_authwit( + context: &mut PrivateContext, + on_behalf_of: AztecAddress, + inner_hash: Field +) { // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter. let result: Field = context.static_call_private_function( on_behalf_of, @@ -262,7 +266,11 @@ pub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_ * * @param on_behalf_of The address that have authorized the `inner_hash` */ -pub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) { +pub fn assert_inner_hash_valid_authwit_public( + context: &mut PublicContext, + on_behalf_of: AztecAddress, + inner_hash: Field +) { let result: Field = context.call_public_function( CANONICAL_AUTH_REGISTRY_ADDRESS, comptime { @@ -338,7 +346,12 @@ pub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) * @param version The version of the chain that the message is being consumed on * @param inner_hash The hash of the "inner" message that is being consumed */ -pub fn compute_authwit_message_hash(consumer: AztecAddress, chain_id: Field, version: Field, inner_hash: Field) -> Field { +pub fn compute_authwit_message_hash( + consumer: AztecAddress, + chain_id: Field, + version: Field, + inner_hash: Field +) -> Field { poseidon2_hash_with_separator( [ consumer.to_field(), diff --git a/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr b/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr index aa7bb176c0f..6df5a120fbc 100644 --- a/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr +++ b/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr @@ -2,14 +2,15 @@ use dep::protocol_types::traits::Empty; // These inputs will likely go away once the AVM processes 1 public kernel per enqueued call. struct PublicContextInputs { - args_hash: Field, + // TODO: Remove this structure and get calldata size at compile time. + calldata_length: Field, is_static_call: bool } impl Empty for PublicContextInputs { fn empty() -> Self { PublicContextInputs { - args_hash: 0, + calldata_length: 0, is_static_call: false } } diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index 762fde1c1c8..5bc56f947f9 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -5,14 +5,16 @@ use dep::protocol_types::traits::{Serialize, Deserialize, Empty}; use dep::protocol_types::abis::function_selector::FunctionSelector; use crate::context::inputs::public_context_inputs::PublicContextInputs; use crate::context::gas::GasOpts; +use crate::hash::ArgsHasher; struct PublicContext { inputs: PublicContextInputs, + args_hash: Option } impl PublicContext { pub fn new(inputs: PublicContextInputs) -> Self { - PublicContext { inputs } + PublicContext { inputs, args_hash: Option::none() } } pub fn emit_unencrypted_log(_self: &mut Self, log: T) where T: Serialize { @@ -130,8 +132,20 @@ impl PublicContext { fn selector(_self: Self) -> FunctionSelector { FunctionSelector::from_u32(function_selector()) } - fn get_args_hash(self) -> Field { - self.inputs.args_hash + fn get_args_hash(mut self) -> Field { + if !self.args_hash.is_some() { + let mut hasher = ArgsHasher::new(); + + // TODO: this should be replaced with the compile-time calldata size. + for i in 0..self.inputs.calldata_length as u32 { + let argn: [Field; 1] = calldata_copy((2 + i) as u32, 1); + hasher.add(argn[0]); + } + + self.args_hash = Option::some(hasher.hash()); + } + + self.args_hash.unwrap() } fn transaction_fee(_self: Self) -> Field { transaction_fee() @@ -278,6 +292,10 @@ unconstrained fn call_static( call_static_opcode(gas, address, args, function_selector) } +unconstrained fn calldata_copy(cdoffset: u32, copy_size: u32) -> [Field; N] { + calldata_copy_opcode(cdoffset, copy_size) +} + unconstrained fn storage_read(storage_slot: Field) -> Field { storage_read_opcode(storage_slot) } @@ -356,6 +374,9 @@ unconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: Fie #[oracle(avmOpcodeSendL2ToL1Msg)] unconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {} +#[oracle(avmOpcodeCalldataCopy)] +unconstrained fn calldata_copy_opcode(cdoffset: u32, copy_size: u32) -> [Field; N] {} + #[oracle(avmOpcodeCall)] unconstrained fn call_opcode( gas: [Field; 2], // gas allocation: [l2_gas, da_gas] diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr index 39af0fba85a..eaa143772bc 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr @@ -137,12 +137,12 @@ mod test { } }; - /// 1. `EncryptedLogIncomingBody::from_note` calls `note.to_be_bytes(storage_slot)` function which serializes - /// the note to bytes - note that in the case of `AddressNote` the `to_be_bytes` function was automatically - /// implemented by Aztec macros. + // 1. `EncryptedLogIncomingBody::from_note` calls `note.to_be_bytes(storage_slot)` function which serializes + // the note to bytes - note that in the case of `AddressNote` the `to_be_bytes` function was automatically + // implemented by Aztec macros. let body = EncryptedLogIncomingBody::from_note(note, storage_slot); - /// 2. `body.compute_ciphertext(...)` function then derives symmetric key from `eph_sk` and `ivpk` and encrypts + // 2. `body.compute_ciphertext(...)` function then derives symmetric key from `eph_sk` and `ivpk` and encrypts // the note plaintext using AES-128. let ciphertext = body.compute_ciphertext(eph_sk, ivpk); diff --git a/noir-projects/aztec-nr/aztec/src/hash.nr b/noir-projects/aztec-nr/aztec/src/hash.nr index 6cca38d1422..3a66e2ca643 100644 --- a/noir-projects/aztec-nr/aztec/src/hash.nr +++ b/noir-projects/aztec-nr/aztec/src/hash.nr @@ -4,14 +4,15 @@ use dep::protocol_types::{ GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT, GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH, MAX_ARGS_LENGTH }, - traits::Hash, - hash::{ - pedersen_hash, compute_siloed_nullifier, sha256_to_field, pedersen_commitment, - poseidon2_hash_with_separator -} + point::Point, traits::Hash, hash::{sha256_to_field, poseidon2_hash_with_separator} }; -// Note: pedersen_commitment is used only as a re-export here -use crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}; +use crate::oracle::logs_traits::ToBytesForUnencryptedLog; + +pub use dep::protocol_types::hash::{compute_siloed_nullifier, pedersen_hash}; + +pub fn pedersen_commitment(inputs: [Field; N], hash_index: u32) -> Point { + std::hash::pedersen_commitment_with_separator(inputs, hash_index) +} pub fn compute_secret_hash(secret: Field) -> Field { poseidon2_hash_with_separator([secret], GENERATOR_INDEX__SECRET_HASH) diff --git a/noir-projects/aztec-nr/aztec/src/history/note_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/note_inclusion.nr index d5779411b6b..6dc078e986b 100644 --- a/noir-projects/aztec-nr/aztec/src/history/note_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/note_inclusion.nr @@ -12,13 +12,15 @@ trait ProveNoteInclusion { impl ProveNoteInclusion for Header { fn prove_note_inclusion(self, note: Note) where Note: NoteInterface { - // 1) Compute note_hash let note_hash = compute_note_hash_for_nullify(note); - // 2) Get the membership witness of the note in the note hash tree - let witness = get_note_hash_membership_witness(self.global_variables.block_number as u32, note_hash); + let witness = unsafe { + get_note_hash_membership_witness(self.global_variables.block_number as u32, note_hash) + }; - // 3) Prove that the commitment is in the note hash tree + // Note inclusion is fairly straightforward, since all we need to prove is that a note exists in the note tree - + // we don't even care _where_ in the tree it is stored. This is because entries in the note hash tree are + // unique. assert_eq( self.state.partial.note_hash_tree.root, root_from_sibling_path(note_hash, witness.index, witness.path), "Proving note inclusion failed" ); diff --git a/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr index 612db617c9c..4c9b89788d1 100644 --- a/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr @@ -13,21 +13,21 @@ trait ProveNullifierInclusion { impl ProveNullifierInclusion for Header { fn prove_nullifier_inclusion(self, nullifier: Field) { // 1) Get the membership witness of the nullifier - let witness = get_nullifier_membership_witness(self.global_variables.block_number as u32, nullifier); + let witness = unsafe { + get_nullifier_membership_witness(self.global_variables.block_number as u32, nullifier) + }; - // 2) Check that the witness we obtained matches the nullifier - assert(witness.leaf_preimage.nullifier == nullifier, "Nullifier does not match value in witness"); - - // 3) Compute the nullifier tree leaf - let nullifier_leaf = witness.leaf_preimage.hash(); - - // 4) Prove that the nullifier is in the nullifier tree + // 2) First we prove that the tree leaf in the witness is present in the nullifier tree. This is expected to be + // the leaf that contains the nullifier we're proving inclusion for. assert( self.state.partial.nullifier_tree.root - == root_from_sibling_path(nullifier_leaf, witness.index, witness.path), "Proving nullifier inclusion failed" + == root_from_sibling_path(witness.leaf_preimage.hash(), witness.index, witness.path), "Proving nullifier inclusion failed" ); - // --> Now we have traversed the trees all the way up to archive root and verified that the nullifier - // was included in the nullifier tree. + + // 3) Then we simply check that the value in the leaf is the expected one. Note that we don't need to perform + // any checks on the rest of the values in the leaf preimage (the next index or next nullifier), since all we + // care about is showing that the tree contains an entry with the expected nullifier. + assert(witness.leaf_preimage.nullifier == nullifier, "Nullifier does not match value in witness"); } } diff --git a/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr index 786edb3c2b8..5238ca99c50 100644 --- a/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr @@ -12,30 +12,31 @@ trait ProveNullifierNonInclusion { impl ProveNullifierNonInclusion for Header { fn prove_nullifier_non_inclusion(self, nullifier: Field) { // 1) Get the membership witness of a low nullifier of the nullifier - let witness = get_low_nullifier_membership_witness(self.global_variables.block_number as u32, nullifier); - - // 2) Prove that the nullifier is not included in the nullifier tree - - // 2.a) Compute the low nullifier leaf and prove that it is in the nullifier tree - let low_nullifier_leaf = witness.leaf_preimage.hash(); + let witness = unsafe { + get_low_nullifier_membership_witness(self.global_variables.block_number as u32, nullifier) + }; + + // 2) First we prove that the tree leaf in the witness is present in the nullifier tree. This is expected to be + // the 'low leaf', i.e. the leaf that would come immediately before the nullifier's leaf, if the nullifier were + // to be in the tree. + let low_nullifier_leaf = witness.leaf_preimage; assert( self.state.partial.nullifier_tree.root - == root_from_sibling_path(low_nullifier_leaf, witness.index, witness.path), "Proving nullifier non-inclusion failed: Could not prove low nullifier inclusion" + == root_from_sibling_path(low_nullifier_leaf.hash(), witness.index, witness.path), "Proving nullifier non-inclusion failed: Could not prove low nullifier inclusion" ); - // 2.b) Prove that the low nullifier is smaller than the nullifier + // 3) Prove that the low leaf is indeed smaller than the nullifier assert( - full_field_less_than(witness.leaf_preimage.nullifier, nullifier), "Proving nullifier non-inclusion failed: low_nullifier.value < nullifier.value check failed" + full_field_less_than(low_nullifier_leaf.nullifier, nullifier), "Proving nullifier non-inclusion failed: low_nullifier.value < nullifier.value check failed" ); - // 2.c) Prove that the low nullifier is pointing "over" the nullifier to prove that the nullifier is not - // included in the nullifier tree (or to 0 if the to-be-inserted nullifier is the largest of all) + // 4) Prove that the low leaf is pointing "over" the nullifier, which means that the nullifier is not included + // in the nullifier tree, since if it were it'd need to be between the low leaf and the next leaf. Note the + // special case in which the low leaf is the largest of all entries, in which case there's no 'next' entry. assert( - full_field_greater_than(witness.leaf_preimage.next_nullifier, nullifier) - | (witness.leaf_preimage.next_index == 0), "Proving nullifier non-inclusion failed: low_nullifier.next_value > nullifier.value check failed" + full_field_greater_than(low_nullifier_leaf.next_nullifier, nullifier) + | (low_nullifier_leaf.next_index == 0), "Proving nullifier non-inclusion failed: low_nullifier.next_value > nullifier.value check failed" ); - // --> Now we have traversed the trees all the way up to archive root and verified that the nullifier - // was not yet included in the nullifier tree. } } diff --git a/noir-projects/aztec-nr/aztec/src/history/public_storage.nr b/noir-projects/aztec-nr/aztec/src/history/public_storage.nr index 07356cbd252..b1d833824fc 100644 --- a/noir-projects/aztec-nr/aztec/src/history/public_storage.nr +++ b/noir-projects/aztec-nr/aztec/src/history/public_storage.nr @@ -12,24 +12,36 @@ trait PublicStorageHistoricalRead { impl PublicStorageHistoricalRead for Header { fn public_storage_historical_read(self, storage_slot: Field, contract_address: AztecAddress) -> Field { - // 1) Compute the leaf slot by siloing the storage slot with the contract address + // 1) Compute the leaf index by siloing the storage slot with the contract address let public_data_tree_index = poseidon2_hash_with_separator( [contract_address.to_field(), storage_slot], GENERATOR_INDEX__PUBLIC_LEAF_INDEX ); - // 2) Get the membership witness of the slot - let witness = get_public_data_witness( - self.global_variables.block_number as u32, - public_data_tree_index + // 2) Get the membership witness for the tree index. + let witness = unsafe { + get_public_data_witness( + self.global_variables.block_number as u32, + public_data_tree_index + ) + }; + + // 3) The witness is made up of two parts: the preimage of the leaf and the proof that it exists in the tree. + // We first prove that the witness is indeed valid for the public data tree, i.e. that the preimage is of a + // value present in the tree. Note that `hash` returns not just the hash of the value but also the metadata + // (slot, next index and next slot). + assert( + self.state.partial.public_data_tree.root + == root_from_sibling_path(witness.leaf_preimage.hash(), witness.index, witness.path), "Proving public value inclusion failed" ); - // 3) Extract the value from the witness leaf and check that the storage slot is correct + // 4) Now that we know the preimage is valid, we determine the value that's represented by this tree entry. Here + // we have two scenarios: + // 1. The tree entry is initialized, and the value is the same as the one in the witness + // 2. The entry was never initialized, and the value is default zero (the default) + // The code below is based on the same checks in `validate_public_data_reads` in `base_rollup_inputs`. let preimage = witness.leaf_preimage; - // Here we have two cases. Code based on same checks in `validate_public_data_reads` in `base_rollup_inputs` - // 1. The value is the same as the one in the witness - // 2. The value was never initialized and is zero let is_less_than_slot = full_field_less_than(preimage.slot, public_data_tree_index); let is_next_greater_than = full_field_less_than(public_data_tree_index, preimage.next_slot); let is_max = ((preimage.next_index == 0) & (preimage.next_slot == 0)); @@ -42,13 +54,6 @@ impl PublicStorageHistoricalRead for Header { preimage.value }; - // 4) Prove that the leaf exists in the public data tree. Note that `hash` returns not just the hash of the value - // but also the metadata (slot, next index and next slot). - assert( - self.state.partial.public_data_tree.root - == root_from_sibling_path(preimage.hash(), witness.index, witness.path), "Proving public value inclusion failed" - ); - value } } diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr b/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr index dc1af573af1..ca4ceb86db7 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr @@ -24,9 +24,7 @@ global KEY_REGISTRY_UPDATE_BLOCKS = 5; global KEY_REGISTRY_STORAGE_SLOT = 1; -// A helper function since requesting nsk_app is very common -// TODO(#6543) -pub fn get_nsk_app(npk_m_hash: Field) -> Field { +unconstrained pub fn get_nsk_app(npk_m_hash: Field) -> Field { get_key_validation_request(npk_m_hash, NULLIFIER_INDEX).sk_app } diff --git a/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr b/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr index 23561941671..25d66fe899d 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr @@ -80,13 +80,17 @@ pub fn get_note( context: &mut PrivateContext, storage_slot: Field ) -> (Note, Field) where Note: NoteInterface { - let note = get_note_internal(storage_slot); + let note = unsafe { + get_note_internal(storage_slot) + }; + // Constraining that we got a valid note from the oracle is fairly straightforward: all we need to do is check that + // the metadata is correct, and that the note exists. check_note_header(*context, storage_slot, note); let note_hash_for_read_request = compute_note_hash_for_read_request(note); - context.push_note_hash_read_request(note_hash_for_read_request); + (note, note_hash_for_read_request) } @@ -95,8 +99,12 @@ pub fn get_notes( storage_slot: Field, options: NoteGetterOptions ) -> (BoundedVec, BoundedVec) where Note: NoteInterface + Eq { - let opt_notes = get_notes_internal(storage_slot, options); + let opt_notes = unsafe { + get_notes_internal(storage_slot, options) + }; + // We apply the constraints in a separate function instead of inlining them here to make it easier to test that + // these checks correctly reject bad notes. constrain_get_notes_internal(context, storage_slot, opt_notes, options) } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr index 84a017a5ea0..f9fcad78f38 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr @@ -19,8 +19,13 @@ unconstrained pub fn get_contract_instance_internal_avm(address: AztecAddress) - } pub fn get_contract_instance(address: AztecAddress) -> ContractInstance { - let instance = ContractInstance::deserialize(get_contract_instance_internal(address)); - assert(instance.to_address().eq(address)); + let instance = unsafe { + ContractInstance::deserialize(get_contract_instance_internal(address)) + }; + // The to_address function combines all values in the instance object to produce an address, so by checking that we + // get the expected address we validate the entire struct. + assert_eq(instance.to_address(), address); + instance } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr index 89ac1f84364..8c0f76f5eb8 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr @@ -1,7 +1,4 @@ -use dep::protocol_types::{ - constants::PUBLIC_DATA_TREE_HEIGHT, public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, - utils::arr_copy_slice -}; +use dep::protocol_types::{constants::PUBLIC_DATA_TREE_HEIGHT, data::PublicDataTreeLeafPreimage, utils::arr_copy_slice}; global LEAF_PREIMAGE_LENGTH: u32 = 4; global PUBLIC_DATA_WITNESS: Field = 45; @@ -18,7 +15,10 @@ unconstrained fn get_public_data_witness_oracle( _public_data_tree_index: Field ) -> [Field; PUBLIC_DATA_WITNESS] {} -unconstrained pub fn get_public_data_witness(block_number: u32, public_data_tree_index: Field) -> PublicDataWitness { +unconstrained pub fn get_public_data_witness( + block_number: u32, + public_data_tree_index: Field +) -> PublicDataWitness { let fields = get_public_data_witness_oracle(block_number, public_data_tree_index); PublicDataWitness { index: fields[0], diff --git a/noir-projects/aztec-nr/aztec/src/oracle/header.nr b/noir-projects/aztec-nr/aztec/src/oracle/header.nr index da388b948dd..444419ccec4 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/header.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/header.nr @@ -34,7 +34,9 @@ pub fn get_header_at(block_number: u32, context: PrivateContext) -> Header { ); // 3) Get the header hint of a given block from an oracle - let historical = get_header_at_internal(block_number); + let historical = unsafe { + get_header_at_internal(block_number) + }; // 4) We make sure that the header hint we received from the oracle exists in the state tree and is the actual header // at the desired block number @@ -60,7 +62,9 @@ fn constrain_get_header_at_internal( let block_hash = header_hint.hash(); // 2) Get the membership witness of the block in the archive tree - let witness = get_archive_membership_witness(last_archive_block_number, block_hash); + let witness = unsafe { + get_archive_membership_witness(last_archive_block_number, block_hash) + }; // 3) Check that the block is in the archive (i.e. the witness is valid) assert( diff --git a/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr b/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr index d36d8128bdf..2a9eb412c9c 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr @@ -14,7 +14,9 @@ unconstrained fn get_key_validation_request_internal( KeyValidationRequest::deserialize(result) } -pub fn get_key_validation_request(pk_m_hash: Field, key_index: Field) -> KeyValidationRequest { +unconstrained pub fn get_key_validation_request( + pk_m_hash: Field, + key_index: Field +) -> KeyValidationRequest { get_key_validation_request_internal(pk_m_hash, key_index) } - diff --git a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr index 0c4f3c5f579..de41594fbf9 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/keys.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/keys.nr @@ -4,12 +4,8 @@ use dep::protocol_types::{address::{AztecAddress, PartialAddress}, point::Point} #[oracle(getPublicKeysAndPartialAddress)] unconstrained fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 13] {} -unconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: AztecAddress) -> [Field; 13] { - get_public_keys_and_partial_address_oracle(address) -} - -pub fn get_public_keys_and_partial_address(address: AztecAddress) -> (PublicKeys, PartialAddress) { - let result = get_public_keys_and_partial_address_oracle_wrapper(address); +unconstrained pub fn get_public_keys_and_partial_address(address: AztecAddress) -> (PublicKeys, PartialAddress) { + let result = get_public_keys_and_partial_address_oracle(address); let keys = PublicKeys { npk_m: NpkM { inner: Point { x: result[0], y: result[1], is_infinite: result[2] as bool } }, diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index b054ae17c8b..dcd219d9ad2 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -70,13 +70,15 @@ impl PrivateMutable where Note: NoteInter // docs:end:replace pub fn initialize_or_replace(self, note: &mut Note) -> NoteEmission { - let is_initialized = check_nullifier_exists(self.compute_initialization_nullifier()); + let is_initialized = unsafe { + check_nullifier_exists(self.compute_initialization_nullifier()) + }; - // check_nullifier_exists() is an unconstrained function - we can constrain a true value by providing an - // inclusion proof of the nullifier, but cannot constrain a false value since a non-inclusion proof would only + // check_nullifier_exists() is an unconstrained function - we can constrain a true value by providing an + // inclusion proof of the nullifier, but cannot constrain a false value since a non-inclusion proof would only // be valid if done in public. // Ultimately, this is not an issue ginen that we'll either: - // - initialize the state variable, which would fail if it was already initialized due to the duplicate + // - initialize the state variable, which would fail if it was already initialized due to the duplicate // nullifier, or // - replace the current value, which would fail if it was not initialized since we wouldn't be able to produce // an inclusion proof for the current note diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr index e220c014f8f..dfd458c3915 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr @@ -97,27 +97,28 @@ impl SharedMutable AztecAddress { oracle_get_msg_sender() } @@ -187,3 +191,6 @@ unconstrained fn oracle_get_function_selector() -> FunctionSelector {} #[oracle(setFunctionSelector)] unconstrained fn oracle_set_function_selector(selector: FunctionSelector) {} + +#[oracle(setCalldata)] +unconstrained fn oracle_set_calldata(calldata: [Field]) {} diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr index 13b41096b62..b5b6c20a554 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr @@ -164,18 +164,22 @@ impl TestEnvironment { let original_fn_selector = cheatcodes::get_function_selector(); let target_address = call_interface.get_contract_address(); let fn_selector = call_interface.get_selector(); + let calldata = call_interface.get_args(); cheatcodes::set_fn_selector(fn_selector); cheatcodes::set_contract_address(target_address); cheatcodes::set_msg_sender(original_contract_address); let mut inputs = cheatcodes::get_public_context_inputs(); - inputs.args_hash = hash_args(call_interface.get_args()); + inputs.calldata_length = call_interface.get_args().len() as Field; inputs.is_static_call = call_interface.get_is_static(); + cheatcodes::set_calldata(calldata); + let result = original_fn(inputs); cheatcodes::set_fn_selector(original_fn_selector); cheatcodes::set_contract_address(original_contract_address); cheatcodes::set_msg_sender(original_msg_sender); + cheatcodes::set_calldata(calldata); result } diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr index a6a7199bab1..ca87dd252f5 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr @@ -82,17 +82,22 @@ impl Deployer { let original_msg_sender = cheatcodes::get_msg_sender(); let original_contract_address = get_contract_address(); let original_fn_selector = cheatcodes::get_function_selector(); + let calldata = call_interface.get_args(); cheatcodes::set_fn_selector(call_interface.get_selector()); cheatcodes::set_contract_address(instance.to_address()); cheatcodes::set_msg_sender(original_contract_address); let mut inputs = cheatcodes::get_public_context_inputs(); - inputs.args_hash = hash_args(call_interface.get_args()); + inputs.calldata_length = call_interface.get_args().len() as Field; + inputs.is_static_call = call_interface.get_is_static(); + cheatcodes::set_calldata(calldata); + let _result: T = original_fn(inputs); cheatcodes::set_fn_selector(original_fn_selector); cheatcodes::set_contract_address(original_contract_address); cheatcodes::set_msg_sender(original_msg_sender); + cheatcodes::set_calldata(calldata); instance } diff --git a/noir-projects/aztec-nr/aztec/src/utils/collapse_array.nr b/noir-projects/aztec-nr/aztec/src/utils/collapse_array.nr index aaa531b945e..9ce61ada28c 100644 --- a/noir-projects/aztec-nr/aztec/src/utils/collapse_array.nr +++ b/noir-projects/aztec-nr/aztec/src/utils/collapse_array.nr @@ -6,6 +6,11 @@ use dep::protocol_types::traits::Eq; // this returns // collapsed: [3, 1] pub fn collapse_array(input: [Option; N]) -> BoundedVec where T: Eq { + // Computing the collpased BoundedVec would result in a very large number of constraints, since we'd need to loop + // over the input array and conditionally write to a dynamic vec index, which is a very unfriendly pattern to the + // proving backend. + // Instead, we use an unconstrained function to produce the final collapsed array, along with some hints, and then + // verify that the input and collapsed arrays are equivalent. let (collapsed, collapsed_to_input_index_mapping) = unsafe { get_collapse_hints(input) }; @@ -13,7 +18,7 @@ pub fn collapse_array(input: [Option; N]) -> BoundedVec collapsed } -pub fn verify_collapse_hints( +fn verify_collapse_hints( input: [Option; N], collapsed: BoundedVec, collapsed_to_input_index_mapping: BoundedVec diff --git a/noir-projects/aztec-nr/aztec/src/utils/mod.nr b/noir-projects/aztec-nr/aztec/src/utils/mod.nr index 6412e14c7f7..6c7659da7bb 100644 --- a/noir-projects/aztec-nr/aztec/src/utils/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/utils/mod.nr @@ -3,4 +3,4 @@ mod comparison; mod point; mod test; -use crate::utils::collapse_array::{collapse_array, verify_collapse_hints}; +use crate::utils::collapse_array::collapse_array; diff --git a/noir-projects/aztec-nr/uint-note/Nargo.toml b/noir-projects/aztec-nr/uint-note/Nargo.toml new file mode 100644 index 00000000000..b04f25f78d4 --- /dev/null +++ b/noir-projects/aztec-nr/uint-note/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "uint_note" +authors = ["aztec-labs"] +compiler_version = ">=0.18.0" +type = "lib" + +[dependencies] +aztec = { path = "../aztec" } diff --git a/noir-projects/aztec-nr/uint-note/src/lib.nr b/noir-projects/aztec-nr/uint-note/src/lib.nr new file mode 100644 index 00000000000..2225eccc2a2 --- /dev/null +++ b/noir-projects/aztec-nr/uint-note/src/lib.nr @@ -0,0 +1 @@ +mod uint_note; diff --git a/noir-projects/aztec-nr/uint-note/src/uint_note.nr b/noir-projects/aztec-nr/uint-note/src/uint_note.nr new file mode 100644 index 00000000000..21386337815 --- /dev/null +++ b/noir-projects/aztec-nr/uint-note/src/uint_note.nr @@ -0,0 +1,110 @@ +use dep::aztec::{ + generators::{Ga1 as G_amt, Ga2 as G_npk, Ga3 as G_rnd, G_slot}, + prelude::{NoteHeader, NoteInterface, PrivateContext}, + protocol_types::{ + constants::GENERATOR_INDEX__NOTE_NULLIFIER, point::{Point, POINT_LENGTH}, scalar::Scalar, + hash::poseidon2_hash_with_separator, traits::Serialize +}, + note::utils::compute_note_hash_for_nullify, oracle::unsafe_rand::unsafe_rand, + keys::getters::get_nsk_app +}; +use dep::std::{embedded_curve_ops::multi_scalar_mul, hash::from_field_unsafe}; + +global UINT_NOTE_LEN: Field = 3; // 3 plus a header. +global UINT_NOTE_BYTES_LEN: Field = 3 * 32 + 64; + +#[aztec(note)] +struct UintNote { + // The integer stored by the note + value: U128, + // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. + npk_m_hash: Field, + // Randomness of the note to hide its contents + randomness: Field, +} + +impl NoteInterface for UintNote { + fn compute_nullifier(self, context: &mut PrivateContext, note_hash_for_nullify: Field) -> Field { + let secret = context.request_nsk_app(self.npk_m_hash); + poseidon2_hash_with_separator([ + note_hash_for_nullify, + secret + ], + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ) + } + + fn compute_nullifier_without_context(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_nullify(self); + let secret = get_nsk_app(self.npk_m_hash); + poseidon2_hash_with_separator([note_hash_for_nullify, secret],GENERATOR_INDEX__NOTE_NULLIFIER) + } + + fn compute_note_hiding_point(self) -> Point { + // We use the unsafe version because the multi_scalar_mul will constrain the scalars. + let amount_scalar = from_field_unsafe(self.value.to_integer()); + let npk_m_hash_scalar = from_field_unsafe(self.npk_m_hash); + let randomness_scalar = from_field_unsafe(self.randomness); + let slot_scalar = from_field_unsafe(self.header.storage_slot); + // We compute the note hiding point as: + // `G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness + G_slot * slot` + // instead of using pedersen or poseidon2 because it allows us to privately add and subtract from amount + // in public by leveraging homomorphism. + multi_scalar_mul( + [G_amt, G_npk, G_rnd, G_slot], + [amount_scalar, npk_m_hash_scalar, randomness_scalar, slot_scalar] + ) + } +} + +impl UintNote { + // TODO: Merge this func with `compute_note_hiding_point`. I (benesjan) didn't do it in the initial PR to not have + // to modify macros and all the related funcs in it. + fn to_note_hiding_point(self) -> UintNoteHidingPoint { + UintNoteHidingPoint::new(self.compute_note_hiding_point()) + } +} + +struct UintNoteHidingPoint { + inner: Point +} + +impl UintNoteHidingPoint { + fn new(point: Point) -> Self { + Self { inner: point } + } + + fn add_amount(&mut self, amount: U128) { + self.inner = multi_scalar_mul([G_amt], [from_field_unsafe(amount.to_integer())]) + self.inner; + } + + fn add_npk_m_hash(&mut self, npk_m_hash: Field) { + self.inner = multi_scalar_mul([G_npk], [from_field_unsafe(npk_m_hash)]) + self.inner; + } + + fn add_randomness(&mut self, randomness: Field) { + self.inner = multi_scalar_mul([G_rnd], [from_field_unsafe(randomness)]) + self.inner; + } + + fn add_slot(&mut self, slot: Field) { + self.inner = multi_scalar_mul([G_slot], [from_field_unsafe(slot)]) + self.inner; + } + + fn finalize(self) -> Field { + self.inner.x + } +} + +impl Serialize for UintNoteHidingPoint { + fn serialize(self) -> [Field; POINT_LENGTH] { + self.inner.serialize() + } +} + +impl Eq for UintNote { + fn eq(self, other: Self) -> bool { + (self.value == other.value) & + (self.npk_m_hash == other.npk_m_hash) & + (self.randomness == other.randomness) + } +} diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index d1d39741e0f..38809bc7e54 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -13,11 +13,6 @@ global VALUE_NOTE_LEN: Field = 3; // 3 plus a header. // VALUE_NOTE_LEN * 32 + 32(storage_slot as bytes) + 32(note_type_id as bytes) global VALUE_NOTE_BYTES_LEN: Field = 3 * 32 + 64; -trait OwnedNote { - fn new(amount: U128, owner_npk_m_hash: Field) -> Self; - fn get_amount(self) -> U128; -} - // docs:start:value-note-def #[aztec(note)] struct ValueNote { @@ -105,21 +100,6 @@ impl Eq for ValueNote { } } -impl OwnedNote for ValueNote { - fn new(value: U128, owner_npk_m_hash: Field) -> Self { - Self { - value: value.to_field(), - npk_m_hash: owner_npk_m_hash, - randomness: unsafe_rand(), - header: NoteHeader::empty(), - } - } - - fn get_amount(self) -> U128 { - U128::from_field(self.value) - } -} - struct ValueNoteHidingPoint { inner: Point } diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index 81ef861d364..f621ba153ae 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -22,6 +22,7 @@ contract AvmTest { global big_field_128_bits: Field = 0x001234567890abcdef1234567890abcdef; global big_field_136_bits: Field = 0x991234567890abcdef1234567890abcdef; + global big_field_254_bits: Field = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; // Libs use std::embedded_curve_ops::{multi_scalar_mul, EmbeddedCurvePoint}; @@ -125,6 +126,11 @@ contract AvmTest { big_field_136_bits } + #[aztec(public)] + fn set_opcode_really_big_field() -> Field { + big_field_254_bits + } + #[aztec(public)] fn add_u128(a: U128, b: U128) -> U128 { a + b diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index 1b83782f9e6..2d678006e7f 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -18,6 +18,7 @@ trait OwnedNote { global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. global TOKEN_NOTE_BYTES_LEN: Field = 3 * 32 + 64; +// docs:start:TokenNote #[aztec(note)] struct TokenNote { // The amount of tokens in the note @@ -27,6 +28,7 @@ struct TokenNote { // Randomness of the note to hide its contents randomness: Field, } +// docs:end:TokenNote impl NoteInterface for TokenNote { // docs:start:nullifier diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/main.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/main.nr index de1cd87646b..1a5ca5e8fdc 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/main.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/main.nr @@ -344,28 +344,24 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { // Making a call to this function causes a "stack too deep" error, so I've put the body of that function here, instead: // let fracs = __compute_fracs(z, ys); // { y_i / (z - ω^i) } - /** - * - * Note: it's more efficient (saving 30k constraints) to compute: - * ___d-1 - * \ / y_i \ - * / | --------- | . ω^i - * /____ \ z - ω^i / - * i=0 - * ^^^^^^^^^ - * frac - * - * ... than to compute: - * - * ___d-1 - * \ / ω^i \ - * / y_i . | --------- | - * /____ \ z - ω^i / - * i=0 - * - * perhaps because all the ω^i terms are constant witnesses? - * - */ + // Note: it's more efficient (saving 30k constraints) to compute: + // ___d-1 + // \ / y_i \ + // / | --------- | . ω^i + // /____ \ z - ω^i / + // i=0 + // ^^^^^^^^^ + // frac + // + // ... than to compute: + // + // ___d-1 + // \ / ω^i \ + // / y_i . | --------- | + // /____ \ z - ω^i / + // i=0 + // + // perhaps because all the ω^i terms are constant witnesses? //***************************************************************** // This section is only needed because `__compute_fracs` isn't working (stack too deep error). @@ -415,28 +411,25 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { // which implies...we can accomodate up to EIGHT additions of product terms before we risk overflowing // (this is really messy! I never considered the case of giant linear sequences of products) let mut sum: F = BigNum::new(); - /** - * Seeking: - * ___d-1 - * \ ω^i - * sum = / y_i . --------- - * /____ z - ω^i - * i=0 - */ + + // Seeking: + // ___d-1 + // \ ω^i + // sum = / y_i . --------- + // /____ z - ω^i + // i=0 let NUM_PARTIAL_SUMS = FIELDS_PER_BLOB / 8; for i in 0..NUM_PARTIAL_SUMS { let mut partial_sum: F = BigNum::new(); let mut lhs: [F; 8] = [BigNum::new(); 8]; let mut rhs = lhs; - /** - * Seeking: - * ___i*8 + 7 - * \ ω^k - * partial_sum = / y_k . --------- - * /____ z - ω^k - * k=i*8 + 0 - */ + // Seeking: + // ___i*8 + 7 + // \ ω^k + // partial_sum = / y_k . --------- + // /____ z - ω^k + // k=i*8 + 0 for j in 0..8 { let k = i * 8 + j; @@ -459,26 +452,25 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { std::as_witness(partial_sum.limbs[2]); } - /** - * Seeking: - * ___i*8 - 1 ___i*8 + 7 - * \ ω^i \ / y_k \ - * sum_out = / y_i . --------- + / ω^k . | --------- | - * /____ z - ω^i /____ \ z - ω^k / - * 0 k = i*8 - * ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * sum partial_sum - * - * ... that is: - * - * ___i*8 - 1 ___ 7 - * \ ω^i \ - * sum_out = / y_i . --------- + / lhs[j] . rhs[j] - * /____ z - ω^i /____ - * 0 j = 0 - * ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ - * sum partial_sum - */ + // Seeking: + // ___i*8 - 1 ___i*8 + 7 + // \ ω^i \ / y_k \ + // sum_out = / y_i . --------- + / ω^k . | --------- | + // /____ z - ω^i /____ \ z - ω^k / + // 0 k = i*8 + // ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + // sum partial_sum + // + // ... that is: + // + // ___i*8 - 1 ___ 7 + // \ ω^i \ + // sum_out = / y_i . --------- + / lhs[j] . rhs[j] + // /____ z - ω^i /____ + // 0 j = 0 + // ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + // sum partial_sum + // let mut sum_out = sum.__add(partial_sum); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr index 177fece92e4..626355ec44f 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr @@ -13,7 +13,9 @@ struct PreviousKernelValidator { impl PreviousKernelValidator { pub fn new(previous_kernel: PrivateKernelCircuitPublicInputs) -> Self { - let hints = generate_previous_kernel_validator_hints(previous_kernel); + let hints = unsafe { + generate_previous_kernel_validator_hints(previous_kernel) + }; PreviousKernelValidator { previous_kernel, hints } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr index ae0463425d3..a3a0483dfdf 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr @@ -8,23 +8,16 @@ use crate::components::private_call_data_validator::{ use dep::types::{ abis::{ call_context::CallContext, kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, - log_hash::NoteLogHash, note_hash::ScopedNoteHash, private_call_request::PrivateCallRequest, - private_circuit_public_inputs::{PrivateCircuitPublicInputs, PrivateCircuitPublicInputsArrayLengths}, + note_hash::ScopedNoteHash, private_call_request::PrivateCallRequest, + private_circuit_public_inputs::PrivateCircuitPublicInputsArrayLengths, private_kernel::private_call_data::PrivateCallData, side_effect::{Ordered, RangeOrdered} }, address::{AztecAddress, PartialAddress}, contract_class_id::ContractClassId, constants::MAX_FIELD_VALUE, hash::{private_functions_root_from_siblings, stdlib_recursion_verification_key_compress_native_vk}, - traits::is_empty, transaction::tx_request::TxRequest, utils::arrays::find_index_hint + transaction::tx_request::TxRequest, utils::arrays::find_index_hint }; -unconstrained fn find_first_revertible_private_call_request_index(public_inputs: PrivateCircuitPublicInputs) -> u32 { - find_first_revertible_item_index( - public_inputs.min_revertible_side_effect_counter, - public_inputs.private_call_requests - ) -} - fn validate_call_context( target_contract: AztecAddress, target_context: CallContext, @@ -261,15 +254,20 @@ impl PrivateCallDataValidator { // Check that the min_revertible_side_effect_counter does not fall in the middle of any nested calls. // If it is possible, one can create a custom account contract, set the min_revertible_side_effect_counter to a - // value that falls in a transfer function, make the tx revert which then preserves the note hashes and discards + // value that falls in a transfer function, make the tx revert which then preserves the note hashes and discards // the nullifiers. - // + // // We don't have to use the aggregated min_revertible_side_effect_counter in the output for the below check. // If the current call's min_revertible_side_effect_counter is 0, it means the counter might be set by another - // function. This check for that function guarantees that the counter won't fall into one of its nested calls. + // function. This check for that function guarantees that the counter won't fall into one of its nested calls. // In this case, we can simply use 0 and make the following check pass. let min_revertible_side_effect_counter = public_inputs.min_revertible_side_effect_counter; - let first_revertible_index = find_first_revertible_private_call_request_index(public_inputs); + let first_revertible_index = unsafe { + find_first_revertible_item_index( + public_inputs.min_revertible_side_effect_counter, + public_inputs.private_call_requests + ) + }; validate_split_ranges( min_revertible_side_effect_counter, first_revertible_index, @@ -393,10 +391,12 @@ impl PrivateCallDataValidator { should_check &= i != num_logs; if should_check { let note_log = note_logs[i]; - let note_index = find_index_hint( - accumulated_note_hashes, - |n: ScopedNoteHash| n.counter() == note_log.note_hash_counter - ); + let note_index = unsafe { + find_index_hint( + accumulated_note_hashes, + |n: ScopedNoteHash| n.counter() == note_log.note_hash_counter + ) + }; assert(note_index != N, "could not find note hash linked to note log"); assert_eq( note_log.note_hash_counter, accumulated_note_hashes[note_index].counter(), "could not find note hash linked to note log" diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/find_first_revertible_item_index.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/find_first_revertible_item_index.nr index 81a87d7b206..2fde0424d62 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/find_first_revertible_item_index.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/find_first_revertible_item_index.nr @@ -1,6 +1,6 @@ use dep::types::{abis::side_effect::Ordered, traits::Empty, utils::arrays::array_length}; -pub fn find_first_revertible_item_index( +unconstrained pub fn find_first_revertible_item_index( min_revertible_side_effect_counter: u32, items: [T; N] ) -> u32 where T: Ordered + Empty + Eq { @@ -31,20 +31,22 @@ mod tests { TestBuilder { private_call } } - pub fn execute(self) -> u32 { + pub fn execute_to_equal(self, expected: u32) { let private_call = self.private_call.to_private_circuit_public_inputs(); - find_first_revertible_item_index( - private_call.min_revertible_side_effect_counter, - private_call.private_call_requests - ) + let index = unsafe { + find_first_revertible_item_index( + private_call.min_revertible_side_effect_counter, + private_call.private_call_requests + ) + }; + assert_eq(index, expected); } } #[test] fn find_first_revertible_item_index_empty() { let builder = TestBuilder::new(); - let index = builder.execute(); - assert_eq(index, 0); + builder.execute_to_equal(0); } #[test] @@ -53,8 +55,7 @@ mod tests { builder.private_call.min_revertible_side_effect_counter = 5; - let index = builder.execute(); - assert_eq(index, 0); + builder.execute_to_equal(0); } #[test] @@ -65,8 +66,7 @@ mod tests { builder.private_call.end_setup(); builder.private_call.append_private_call_requests(3); - let index = builder.execute(); - assert_eq(index, 0); + builder.execute_to_equal(0); } #[test] @@ -77,8 +77,7 @@ mod tests { builder.private_call.append_private_call_requests(2); builder.private_call.end_setup(); - let index = builder.execute(); - assert_eq(index, 2); + builder.execute_to_equal(2); } #[test] @@ -91,7 +90,6 @@ mod tests { builder.private_call.end_setup(); builder.private_call.append_private_call_requests(3); - let index = builder.execute(); - assert_eq(index, 2); + builder.execute_to_equal(2); } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr index fd967b2572c..b15ba665b3e 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr @@ -1,6 +1,6 @@ use dep::types::abis::side_effect::RangeOrdered; -pub fn validate_split_ranges( +pub fn validate_split_ranges( min_revertible_side_effect_counter: u32, first_revertible_item_index: u32, items: [T; N], diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr index fb9ebb60c9f..d52adc43ff1 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr @@ -4,7 +4,7 @@ use dep::types::{ kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsArrayLengths}, max_block_number::MaxBlockNumber, private_circuit_public_inputs::{PrivateCircuitPublicInputs, PrivateCircuitPublicInputsArrayLengths}, - private_kernel::private_call_data::PrivateCallData, side_effect::Scoped + side_effect::Scoped }, address::AztecAddress, traits::{Empty, is_empty}, transaction::tx_request::TxRequest }; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr index 5b72fd5ec4a..1f935ba9ec3 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr @@ -5,12 +5,7 @@ use dep::types::{ max_block_number::MaxBlockNumber, nullifier::{Nullifier, ScopedNullifier}, private_circuit_public_inputs::PrivateCircuitPublicInputs }, - address::AztecAddress, - constants::{ - MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_TX, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL -}, - traits::is_empty, transaction::tx_request::TxRequest, + address::AztecAddress, traits::is_empty, transaction::tx_request::TxRequest, utils::arrays::{array_length, array_to_bounded_vec, sort_by_counter_asc, sort_by_counter_desc} }; @@ -99,7 +94,7 @@ impl PrivateKernelCircuitPublicInputsComposer { *self } - pub fn sort_ordered_values(&mut self) { + unconstrained pub fn sort_ordered_values(&mut self) { // Note hashes, nullifiers, note_encrypted_logs_hashes, and encrypted_logs_hashes are sorted in the reset circuit. self.public_inputs.end.l2_to_l1_msgs.storage = sort_by_counter_asc(self.public_inputs.end.l2_to_l1_msgs.storage); self.public_inputs.end.unencrypted_logs_hashes.storage = sort_by_counter_asc(self.public_inputs.end.unencrypted_logs_hashes.storage); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer.nr index c733b4d01b8..bbaf6dbbc0f 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer.nr @@ -1,15 +1,14 @@ mod reset_output_hints; -use crate::components::reset_output_composer::{reset_output_hints::{generate_reset_output_hints, ResetOutputHints}}; -use dep::reset_kernel_lib::{ - KeyValidationHint, NoteHashReadRequestHints, NullifierReadRequestHints, TransientDataIndexHint, - PrivateValidationRequestProcessor -}; +pub use reset_output_hints::ResetOutputHints; + +use crate::components::reset_output_composer::{reset_output_hints::generate_reset_output_hints}; +use dep::reset_kernel_lib::{TransientDataIndexHint, PrivateValidationRequestProcessor}; use dep::types::{ abis::{ kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, log_hash::{NoteLogHash, ScopedEncryptedLogHash}, note_hash::ScopedNoteHash, - nullifier::ScopedNullifier, validation_requests::PrivateValidationRequests + nullifier::ScopedNullifier }, address::AztecAddress, constants::{ @@ -47,7 +46,7 @@ impl< NLL_RR_SETTLED, KEY_VALIDATION_REQUESTS, > { - pub fn new( + unconstrained pub fn new( previous_kernel: PrivateKernelCircuitPublicInputs, validation_request_processor: PrivateValidationRequestProcessor, transient_data_index_hints: [TransientDataIndexHint; TRANSIENT_DATA_AMOUNT], @@ -66,7 +65,7 @@ impl< } } - pub fn finish(self) -> PrivateKernelCircuitPublicInputs { + unconstrained pub fn finish(self) -> PrivateKernelCircuitPublicInputs { let mut output = self.previous_kernel; output.validation_requests = self.validation_request_processor.compose(); @@ -98,7 +97,7 @@ impl< output } - fn get_sorted_siloed_note_hashes(self) -> [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX] { + unconstrained fn get_sorted_siloed_note_hashes(self) -> [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX] { let mut note_hashes = sort_by_counter_asc(self.hints.kept_note_hashes); let first_nullifier = self.previous_kernel.end.nullifiers[0].value(); for i in 0..note_hashes.len() { @@ -112,7 +111,7 @@ impl< note_hashes } - fn get_sorted_siloed_nullifiers(self) -> [ScopedNullifier; MAX_NULLIFIERS_PER_TX] { + unconstrained fn get_sorted_siloed_nullifiers(self) -> [ScopedNullifier; MAX_NULLIFIERS_PER_TX] { let mut nullifiers = sort_by_counter_asc(self.hints.kept_nullifiers); for i in 0..nullifiers.len() { nullifiers[i].nullifier.value = silo_nullifier(nullifiers[i]); @@ -121,7 +120,7 @@ impl< nullifiers } - fn get_sorted_note_encrypted_log_hashes(self) -> [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX] { + unconstrained fn get_sorted_note_encrypted_log_hashes(self) -> [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX] { let mut log_hashes = sort_by_counter_asc(self.hints.kept_note_encrypted_log_hashes); for i in 0..log_hashes.len() { log_hashes[i].note_hash_counter = 0; @@ -129,7 +128,7 @@ impl< log_hashes } - fn get_sorted_masked_encrypted_log_hashes(self) -> [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX] { + unconstrained fn get_sorted_masked_encrypted_log_hashes(self) -> [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX] { let mut log_hashes = sort_by_counter_asc(self.previous_kernel.end.encrypted_logs_hashes); for i in 0..log_hashes.len() { log_hashes[i].contract_address = mask_encrypted_log_hash(log_hashes[i]); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr index 65773bc5357..02d32768979 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr @@ -19,14 +19,14 @@ struct TailOutputComposer { } impl TailOutputComposer { - pub fn new(previous_kernel: PrivateKernelCircuitPublicInputs) -> Self { + unconstrained pub fn new(previous_kernel: PrivateKernelCircuitPublicInputs) -> Self { let mut output_composer = PrivateKernelCircuitPublicInputsComposer::new_from_previous_kernel(previous_kernel); output_composer.sort_ordered_values(); TailOutputComposer { output_composer } } - pub fn finish(self) -> KernelCircuitPublicInputs { + unconstrained pub fn finish(self) -> KernelCircuitPublicInputs { let source = self.output_composer.finish(); let mut output = KernelCircuitPublicInputs::empty(); output.rollup_validation_requests = source.validation_requests.for_rollup; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr index e0585bd0ffe..350c9d69f7f 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr @@ -7,7 +7,7 @@ use dep::types::{ utils::arrays::array_length }; -fn meter_gas_used(data: CombinedAccumulatedData, gas_settings: GasSettings) -> Gas { +pub fn meter_gas_used(data: CombinedAccumulatedData, gas_settings: GasSettings) -> Gas { let mut metered_da_bytes = 0; let mut metered_l2_gas = 0; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr index 4787f401fb3..205819bf0b4 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr @@ -7,7 +7,7 @@ use crate::components::{ use dep::types::{ abis::{ kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs}, - log_hash::{LogHash, NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash} + log_hash::{NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash} }, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::is_empty, utils::arrays::assert_exposed_sorted_transformed_value_array @@ -24,7 +24,9 @@ impl TailOutputValidator { output: KernelCircuitPublicInputs, previous_kernel: PrivateKernelCircuitPublicInputs ) -> Self { - let hints = generate_tail_output_hints(previous_kernel); + let hints = unsafe { + generate_tail_output_hints(previous_kernel) + }; TailOutputValidator { output, previous_kernel, hints } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr index 4b4784de94b..7b945727093 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr @@ -18,14 +18,14 @@ struct TailToPublicOutputComposer { } impl TailToPublicOutputComposer { - pub fn new(previous_kernel: PrivateKernelCircuitPublicInputs) -> Self { + unconstrained pub fn new(previous_kernel: PrivateKernelCircuitPublicInputs) -> Self { let mut output_composer = PrivateKernelCircuitPublicInputsComposer::new_from_previous_kernel(previous_kernel); output_composer.sort_ordered_values(); TailToPublicOutputComposer { output_composer } } - pub fn finish(self) -> PublicKernelCircuitPublicInputs { + unconstrained pub fn finish(self) -> PublicKernelCircuitPublicInputs { let source = self.output_composer.public_inputs; let mut validation_requests = PublicValidationRequests::empty(); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr index 4d75aa162ab..0f3d2a7183a 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr @@ -1,8 +1,5 @@ use dep::types::{ - abis::{ - accumulated_data::{public_accumulated_data_builder::PublicAccumulatedData}, gas::Gas, - log_hash::{LogHash, ScopedLogHash} -}, + abis::{accumulated_data::PublicAccumulatedData, gas::Gas, log_hash::{LogHash, ScopedLogHash}}, constants::{ DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, FIXED_AVM_STARTUP_L2_GAS, L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, L2_GAS_PER_LOG_BYTE diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr index 0bf6fa0318d..79bc70f7ad1 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr @@ -6,7 +6,7 @@ use dep::types::abis::{ } }; -pub fn split_to_public( +unconstrained pub fn split_to_public( data: PrivateAccumulatedDataBuilder, min_revertible_side_effect_counter: u32 ) -> (PublicAccumulatedData, PublicAccumulatedData) { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr index 1fd619af533..231353cb013 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr @@ -10,11 +10,10 @@ use dep::types::{ log_hash::{LogHash, ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash}, note_hash::ScopedNoteHash, nullifier::{Nullifier, ScopedNullifier}, public_call_request::PublicCallRequest }, - messaging::l2_to_l1_message::ScopedL2ToL1Message, address::AztecAddress, - traits::{is_empty, is_empty_array}, + messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::{is_empty, is_empty_array}, utils::arrays::{ assert_split_sorted_transformed_value_arrays_asc, assert_split_sorted_transformed_value_arrays_desc, - assert_split_transformed_value_arrays, validate_array + assert_split_transformed_value_arrays } }; @@ -29,7 +28,9 @@ impl TailToPublicOutputValidator { output: PublicKernelCircuitPublicInputs, previous_kernel: PrivateKernelCircuitPublicInputs ) -> Self { - let hints = generate_tail_to_public_output_hints(previous_kernel); + let hints = unsafe { + generate_tail_to_public_output_hints(previous_kernel) + }; TailToPublicOutputValidator { output, previous_kernel, hints } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/lib.nr index 5e168498e26..a47d3cd2bc1 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/lib.nr @@ -7,9 +7,9 @@ mod private_kernel_empty; mod private_kernel_reset; mod tests; -use private_kernel_init::PrivateKernelInitCircuitPrivateInputs; -use private_kernel_inner::PrivateKernelInnerCircuitPrivateInputs; -use private_kernel_reset::PrivateKernelResetCircuitPrivateInputs; -use private_kernel_tail::PrivateKernelTailCircuitPrivateInputs; -use private_kernel_tail_to_public::PrivateKernelTailToPublicCircuitPrivateInputs; -use private_kernel_empty::PrivateKernelEmptyPrivateInputs; +pub use private_kernel_init::PrivateKernelInitCircuitPrivateInputs; +pub use private_kernel_inner::PrivateKernelInnerCircuitPrivateInputs; +pub use private_kernel_reset::PrivateKernelResetCircuitPrivateInputs; +pub use private_kernel_tail::PrivateKernelTailCircuitPrivateInputs; +pub use private_kernel_tail_to_public::PrivateKernelTailToPublicCircuitPrivateInputs; +pub use private_kernel_empty::PrivateKernelEmptyPrivateInputs; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index bbab4520c7b..da34dc55e7d 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -31,7 +31,9 @@ impl PrivateKernelInitCircuitPrivateInputs { pub fn execute(self) -> PrivateKernelCircuitPublicInputs { // Generate output. - let output = self.generate_output(); + let output = unsafe { + self.generate_output() + }; // Validate inputs. let private_call_data_validator = PrivateCallDataValidator::new(self.private_call); @@ -56,7 +58,7 @@ mod tests { use crate::private_kernel_init::PrivateKernelInitCircuitPrivateInputs; use dep::types::{ abis::{kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs}, - tests::{fixture_builder::FixtureBuilder, fixtures, utils::assert_array_eq}, + tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq}, transaction::tx_request::TxRequest }; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index 7bd4c789aec..7168efc5a7a 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -42,7 +42,9 @@ impl PrivateKernelInnerCircuitPrivateInputs { pub fn execute(self) -> PrivateKernelCircuitPublicInputs { // Generate output. - let output = self.generate_output(); + let output = unsafe { + self.generate_output() + }; // Validate inputs. let private_call_data_validator = PrivateCallDataValidator::new(self.private_call); @@ -74,7 +76,7 @@ mod tests { use crate::private_kernel_inner::{PrivateKernelInnerCircuitPrivateInputs, ALLOWED_PREVIOUS_CIRCUITS}; use dep::types::{ abis::{kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs}, - constants::{PRIVATE_KERNEL_INIT_INDEX, PRIVATE_KERNEL_INNER_INDEX, BASE_ROLLUP_INDEX}, + constants::PRIVATE_KERNEL_INIT_INDEX, tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq} }; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr index f94339c133f..b06e27d3c64 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr @@ -8,8 +8,7 @@ use dep::reset_kernel_lib::{ }; use dep::types::{ abis::private_kernel_data::PrivateKernelData, - constants::{MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, PRIVATE_KERNEL_INIT_INDEX, PRIVATE_KERNEL_INNER_INDEX}, - PrivateKernelCircuitPublicInputs + constants::{PRIVATE_KERNEL_INIT_INDEX, PRIVATE_KERNEL_INNER_INDEX}, PrivateKernelCircuitPublicInputs }; global ALLOWED_PREVIOUS_CIRCUITS = [ @@ -76,12 +75,14 @@ impl< }; // Generate output. - let (output, output_hints) = self.generate_output( - validation_request_processor, - note_hash_siloing_amount, - nullifier_siloing_amount, - encrypted_log_siloing_amount - ); + let (output, output_hints) = unsafe { + self.generate_output( + validation_request_processor, + note_hash_siloing_amount, + nullifier_siloing_amount, + encrypted_log_siloing_amount + ) + }; // Validate inputs. if !std::runtime::is_unconstrained() { @@ -121,21 +122,18 @@ mod tests { } }; use dep::types::constants::{ - MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, GENERATOR_INDEX__OVSK_M, - PRIVATE_KERNEL_INNER_INDEX, BASE_ROLLUP_INDEX + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, + GENERATOR_INDEX__OVSK_M, PRIVATE_KERNEL_INNER_INDEX }; use dep::types::{ abis::{ kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, - max_block_number::MaxBlockNumber, note_hash::{NoteHash, ScopedNoteHash}, - nullifier::{Nullifier, ScopedNullifier}, log_hash::{NoteLogHash, ScopedEncryptedLogHash}, - read_request::ScopedReadRequest + max_block_number::MaxBlockNumber, note_hash::ScopedNoteHash, nullifier::ScopedNullifier, + log_hash::{NoteLogHash, ScopedEncryptedLogHash} }, address::AztecAddress, hash::{mask_encrypted_log_hash, silo_note_hash, silo_nullifier}, - scalar::Scalar, tests::{fixture_builder::FixtureBuilder, utils::{assert_array_eq, swap_items}}, - utils::{arrays::{array_length, find_index_hint}}, traits::{Empty, is_empty, is_empty_array}, - point::Point + tests::{fixture_builder::FixtureBuilder, utils::{assert_array_eq, swap_items}}, + utils::{arrays::find_index_hint}, traits::is_empty_array, point::Point }; struct PrivateKernelResetInputsBuilder { @@ -195,10 +193,12 @@ mod tests { pub fn nullify_pending_note_hash(&mut self, nullifier_index: u32, note_hash_index: u32) { let note_hash = self.previous_kernel.note_hashes.get(note_hash_index).note_hash; self.previous_kernel.nullifiers.storage[nullifier_index].nullifier.note_hash = note_hash.value; - let num_hints = find_index_hint( - self.transient_data_index_hints, - |hint: TransientDataIndexHint| hint.nullifier_index == MAX_NULLIFIERS_PER_TX - ); + let num_hints = unsafe { + find_index_hint( + self.transient_data_index_hints, + |hint: TransientDataIndexHint| hint.nullifier_index == MAX_NULLIFIERS_PER_TX + ) + }; self.transient_data_index_hints[num_hints] = TransientDataIndexHint { nullifier_index, note_hash_index }; } @@ -243,9 +243,15 @@ mod tests { } pub fn execute(&mut self) -> PrivateKernelCircuitPublicInputs { + let note_hash_read_request_hints = unsafe { + self.note_hash_read_request_hints_builder.to_hints() + }; + let nullifier_read_request_hints = unsafe { + self.nullifier_read_request_hints_builder.to_hints() + }; let hints = PrivateKernelResetHints { - note_hash_read_request_hints: self.note_hash_read_request_hints_builder.to_hints(), - nullifier_read_request_hints: self.nullifier_read_request_hints_builder.to_hints(), + note_hash_read_request_hints, + nullifier_read_request_hints, key_validation_hints: [KeyValidationHint::nada(MAX_KEY_VALIDATION_REQUESTS_PER_TX); 2], transient_data_index_hints: self.transient_data_index_hints, validation_requests_split_counter: self.validation_requests_split_counter diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr index 6463f8e4f85..9f273692cf5 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr @@ -32,7 +32,9 @@ impl PrivateKernelTailCircuitPrivateInputs { pub fn execute(self) -> KernelCircuitPublicInputs { // Generate output. - let output = self.generate_output(); + let output = unsafe { + self.generate_output() + }; // Validate inputs. PreviousKernelValidator::new(self.previous_kernel.public_inputs).validate_for_private_tail(); @@ -54,7 +56,7 @@ mod tests { use crate::private_kernel_tail::{PrivateKernelTailCircuitPrivateInputs, ALLOWED_PREVIOUS_CIRCUITS}; use dep::types::constants::{ DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, GENERATOR_INDEX__IVSK_M, L2_GAS_PER_LOG_BYTE, - L2_GAS_PER_NULLIFIER, L2_GAS_PER_NOTE_HASH, PRIVATE_KERNEL_INNER_INDEX, BASE_ROLLUP_INDEX + L2_GAS_PER_NULLIFIER, PRIVATE_KERNEL_INNER_INDEX }; use dep::types::{ abis::{ diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr index 7085b0d1779..48877201b5f 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr @@ -33,7 +33,9 @@ impl PrivateKernelTailToPublicCircuitPrivateInputs { pub fn execute(self) -> PublicKernelCircuitPublicInputs { // Generate output. - let output = self.generate_output(); + let output = unsafe { + self.generate_output() + }; // Validate inputs. PreviousKernelValidator::new(self.previous_kernel.public_inputs).validate_for_private_tail_to_public(); @@ -60,12 +62,12 @@ mod tests { use dep::types::{ abis::{ kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, gas::Gas, - note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, + note_hash::ScopedNoteHash, nullifier::{Nullifier, ScopedNullifier}, log_hash::{LogHash, NoteLogHash} }, address::{AztecAddress, EthAddress}, tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq}, point::Point, - constants::{BASE_ROLLUP_INDEX, PRIVATE_KERNEL_INNER_INDEX} + constants::PRIVATE_KERNEL_INNER_INDEX }; // TODO: Reduce the duplicated code/tests for PrivateKernelTailToPublicInputs and PrivateKernelTailInputs. diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr index 16e28db0d44..4b7888665cc 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr @@ -85,10 +85,7 @@ fn validate_propagated_from_private_call_note_hash_read_requests_output_extra_no * With previous kernel. */ -fn append_note_hash_read_requests_to_previous_kernel( - builder: &mut PrivateKernelCircuitOutputValidatorBuilder, - num_requests: u32 -) { +fn append_note_hash_read_requests_to_previous_kernel(builder: &mut PrivateKernelCircuitOutputValidatorBuilder, num_requests: u32) { builder.previous_kernel.append_note_hash_read_requests(num_requests); builder.output.append_note_hash_read_requests(num_requests); builder.offset_values(num_requests as Field); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr index a71da99fa32..83632225e34 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/reset_output_validator_builder/mod.nr @@ -55,8 +55,12 @@ impl ResetOutputValidatorBuilder { pub fn get_validation_request_processor(self) -> PrivateValidationRequestProcessor<6, 3, 5, 2, 2> { let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); - let note_hash_read_request_hints = self.note_hash_read_request_hints_builder.to_hints(); - let nullifier_read_request_hints = self.nullifier_read_request_hints_builder.to_hints(); + let note_hash_read_request_hints = unsafe { + self.note_hash_read_request_hints_builder.to_hints() + }; + let nullifier_read_request_hints = unsafe { + self.nullifier_read_request_hints_builder.to_hints() + }; PrivateValidationRequestProcessor { validation_requests: previous_kernel.validation_requests, @@ -73,7 +77,9 @@ impl ResetOutputValidatorBuilder { pub fn get_hints(self) -> ResetOutputHints { let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); - generate_reset_output_hints(previous_kernel, self.transient_data_index_hints) + unsafe { + generate_reset_output_hints(previous_kernel, self.transient_data_index_hints) + } } pub fn validate_with_hints(self, hints: ResetOutputHints) { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/mod.nr index 2e230c87155..1b974ed4897 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/mod.nr @@ -16,8 +16,10 @@ impl TailOutputComposerBuilder { pub fn finish(self) -> KernelCircuitPublicInputs { let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); - let composer = TailOutputComposer::new(previous_kernel); - composer.finish() + unsafe { + let composer = TailOutputComposer::new(previous_kernel); + composer.finish() + } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr index db8df7506b5..a1c3159deb7 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr @@ -8,10 +8,7 @@ use crate::components::{ tail_output_validator::{tail_output_hints::{generate_tail_output_hints, TailOutputHints}, TailOutputValidator} }; use dep::types::{ - abis::{ - gas_settings::GasSettings, - kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs} -}, + abis::{gas_settings::GasSettings, kernel_circuit_public_inputs::KernelCircuitPublicInputs}, tests::fixture_builder::FixtureBuilder }; @@ -33,7 +30,9 @@ impl TailOutputValidatorBuilder { pub fn get_hints(self) -> TailOutputHints { let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); - generate_tail_output_hints(previous_kernel) + unsafe { + generate_tail_output_hints(previous_kernel) + } } pub fn export_output(self) -> KernelCircuitPublicInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/mod.nr index 38ecbc234c5..25d7b776f26 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/mod.nr @@ -21,7 +21,9 @@ impl TailToPublicOutputComposerBuilder { pub fn finish(self) -> PublicKernelCircuitPublicInputs { let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); - let composer = TailToPublicOutputComposer::new(previous_kernel); - composer.finish() + unsafe { + let composer = TailToPublicOutputComposer::new(previous_kernel); + composer.finish() + } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr index 31d397eda2f..67b368e0dee 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr @@ -24,10 +24,12 @@ fn split_to_public_succeeds() { builder.append_public_call_requests(2); let combined_data = builder.to_exposed_public_accumulated_data(); - let (non_revertible, revertible) = split_to_public( - builder.to_private_accumulated_data_builder(), - builder.min_revertible_side_effect_counter - ); + let (non_revertible, revertible) = unsafe { + split_to_public( + builder.to_private_accumulated_data_builder(), + builder.min_revertible_side_effect_counter + ) + }; // note_hashes let expected = combined_data.note_hashes; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer.nr index 6f45d5b3c3d..094d013bc99 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer.nr @@ -8,7 +8,6 @@ use dep::types::{ abis::{ accumulated_data::PublicAccumulatedDataBuilder, kernel_circuit_public_inputs::{PublicKernelCircuitPublicInputs, PublicKernelCircuitPublicInputsBuilder}, - public_call_data::PublicCallData, public_call_request::PublicCallRequest, public_circuit_public_inputs::PublicCircuitPublicInputs, public_data_read::PublicDataRead }, traits::is_empty, utils::arrays::array_to_bounded_vec diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer/propagate_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer/propagate_accumulated_data.nr index c3edd3ee575..b1d6c05a13b 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer/propagate_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer/propagate_accumulated_data.nr @@ -1,6 +1,6 @@ use dep::types::{ abis::{ - accumulated_data::PublicAccumulatedDataBuilder, log_hash::LogHash, nullifier::Nullifier, + accumulated_data::PublicAccumulatedDataBuilder, nullifier::Nullifier, public_circuit_public_inputs::PublicCircuitPublicInputs, public_data_update_request::PublicDataUpdateRequest }, diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer.nr index d19f34dbef3..f107f99ad11 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer.nr @@ -1,37 +1,48 @@ mod combine_data; +mod generate_output_hints; +mod generate_overridable_public_data_writes; +mod generate_public_data_leaves; -use crate::components::public_tail_output_composer::combine_data::combine_data; +pub use generate_output_hints::{OutputHints, SiloedNoteHashHint}; +pub use generate_overridable_public_data_writes::LinkedIndexHint; + +use crate::components::public_tail_output_composer::{combine_data::combine_data, generate_output_hints::generate_output_hints}; use dep::types::{ abis::{kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}}, - partial_state_reference::PartialStateReference + data::PublicDataLeafHint, partial_state_reference::PartialStateReference }; -struct PublicTailOutputComposer { +struct PublicTailOutputComposer { previous_kernel: PublicKernelCircuitPublicInputs, start_state: PartialStateReference, + public_data_leaf_hints: [PublicDataLeafHint; NUM_PUBLIC_DATA_LEAVES], } -impl PublicTailOutputComposer { - pub fn new( +impl PublicTailOutputComposer { + unconstrained pub fn new( previous_kernel: PublicKernelCircuitPublicInputs, - start_state: PartialStateReference + start_state: PartialStateReference, + public_data_leaf_hints: [PublicDataLeafHint; NUM_PUBLIC_DATA_LEAVES] ) -> Self { - PublicTailOutputComposer { previous_kernel, start_state } + PublicTailOutputComposer { previous_kernel, start_state, public_data_leaf_hints } } - pub fn finish(self) -> KernelCircuitPublicInputs { + unconstrained pub fn finish(self) -> (KernelCircuitPublicInputs, OutputHints) { + let output_hints = generate_output_hints(self.previous_kernel, self.public_data_leaf_hints); + let end = combine_data( self.previous_kernel.end_non_revertible, - self.previous_kernel.end + self.previous_kernel.end, + output_hints ); - KernelCircuitPublicInputs { + (KernelCircuitPublicInputs { rollup_validation_requests: self.previous_kernel.validation_requests.for_rollup, end, constants: self.previous_kernel.constants, start_state: self.start_state, revert_code: self.previous_kernel.revert_code, fee_payer: self.previous_kernel.fee_payer - } + }, output_hints) } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/combine_data.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/combine_data.nr index 778ccbac6ce..e8e93c8a02d 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/combine_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/combine_data.nr @@ -1,39 +1,22 @@ +use crate::components::public_tail_output_composer::generate_output_hints::OutputHints; use dep::types::{ abis::{ accumulated_data::{CombinedAccumulatedData, PublicAccumulatedData}, log_hash::{LogHash, ScopedLogHash}, nullifier::Nullifier }, - constants::MAX_NOTE_HASHES_PER_TX, hash::silo_note_hash, utils::arrays::{array_merge, dedupe_array, sort_by_counter_asc} }; -unconstrained pub fn combine_data( +unconstrained pub fn combine_data( non_revertible: PublicAccumulatedData, - revertible: PublicAccumulatedData + revertible: PublicAccumulatedData, + output_hints: OutputHints ) -> CombinedAccumulatedData { - let mut note_hashes = [0; MAX_NOTE_HASHES_PER_TX]; - let sorted_unsiloed_note_hashes = sort_by_counter_asc(array_merge(non_revertible.note_hashes, revertible.note_hashes)); - let tx_hash = non_revertible.nullifiers[0].value; - for i in 0..sorted_unsiloed_note_hashes.len() { - let note_hash = sorted_unsiloed_note_hashes[i]; - note_hashes[i] = if note_hash.counter() == 0 { - // If counter is zero, the note hash is either empty or is emitted from private and has been siloed in private_kernel_tail_to_public. - note_hash.value() - } else { - silo_note_hash(note_hash, tx_hash, i) - }; - } - let nullifiers = sort_by_counter_asc(array_merge(non_revertible.nullifiers, revertible.nullifiers)).map(|n: Nullifier| n.value); let l2_to_l1_msgs = sort_by_counter_asc(array_merge(non_revertible.l2_to_l1_msgs, revertible.l2_to_l1_msgs)); - let public_data_update_requests = dedupe_array( - array_merge( - non_revertible.public_data_update_requests, - revertible.public_data_update_requests - ) - ); + let public_data_update_requests = dedupe_array(output_hints.public_data_writes); let note_encrypted_logs_hashes = sort_by_counter_asc( array_merge( @@ -60,7 +43,7 @@ unconstrained pub fn combine_data( let unencrypted_log_preimages_length = unencrypted_logs_hashes.fold(0, |a, b: ScopedLogHash| a + b.log_hash.length); CombinedAccumulatedData { - note_hashes, + note_hashes: output_hints.siloed_note_hashes, nullifiers, l2_to_l1_msgs, note_encrypted_logs_hashes, diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_output_hints.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_output_hints.nr new file mode 100644 index 00000000000..8938c0e166c --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_output_hints.nr @@ -0,0 +1,112 @@ +use crate::components::public_tail_output_composer::{ + generate_overridable_public_data_writes::{generate_overridable_public_data_writes, LinkedIndexHint}, + generate_public_data_leaves::generate_public_data_leaves +}; +use dep::types::{ + abis::{ + kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, + public_data_write::OverridablePublicDataWrite +}, + constants::{ + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX +}, + data::{OverridablePublicDataTreeLeaf, PublicDataLeafHint}, hash::silo_note_hash, traits::Empty, + utils::arrays::{array_merge, CombinedOrderHint, get_combined_order_hints_asc, sort_by_counter_asc, SortedResult} +}; + +struct SiloedNoteHashHint { + siloed_note_hash: Field, + index: u32, +} + +impl Empty for SiloedNoteHashHint { + fn empty() -> Self { + SiloedNoteHashHint { siloed_note_hash: 0, index: 0 } + } +} + +impl Eq for SiloedNoteHashHint { + fn eq(self, other: Self) -> bool { + (self.siloed_note_hash == other.siloed_note_hash) & (self.index == other.index) + } +} + +struct OutputHints { + siloed_note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + siloed_note_hash_hints: [SiloedNoteHashHint; MAX_NOTE_HASHES_PER_TX], + sorted_note_hash_hints: [CombinedOrderHint; MAX_NOTE_HASHES_PER_TX], + sorted_nullifier_hints: [CombinedOrderHint; MAX_NULLIFIERS_PER_TX], + sorted_l2_to_l1_msg_hints: [CombinedOrderHint; MAX_L2_TO_L1_MSGS_PER_TX], + sorted_note_encrypted_log_hash_hints: [CombinedOrderHint; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + sorted_encrypted_log_hash_hints: [CombinedOrderHint; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hash_hints: [CombinedOrderHint; MAX_UNENCRYPTED_LOGS_PER_TX], + public_data_writes: [OverridablePublicDataWrite; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + public_data_leaves: [OverridablePublicDataTreeLeaf; NUM_PUBLIC_DATA_LEAVES], + unique_slot_index_hints: SortedResult, + public_data_linked_index_hints: [LinkedIndexHint; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], +} + +unconstrained pub fn generate_output_hints( + previous_kernel: PublicKernelCircuitPublicInputs, + public_data_leaf_hints: [PublicDataLeafHint; NUM_PUBLIC_DATA_LEAVES] +) -> OutputHints { + let non_revertible = previous_kernel.end_non_revertible; + let revertible = previous_kernel.end; + + // Note hashes. + let mut siloed_note_hashes = [0; MAX_NOTE_HASHES_PER_TX]; + let mut siloed_note_hash_hints = [SiloedNoteHashHint::empty(); MAX_NOTE_HASHES_PER_TX]; + let sorted_unsiloed_note_hashes = sort_by_counter_asc(array_merge(non_revertible.note_hashes, revertible.note_hashes)); + let tx_hash = non_revertible.nullifiers[0].value; + for i in 0..sorted_unsiloed_note_hashes.len() { + let note_hash = sorted_unsiloed_note_hashes[i]; + let siloed_note_hash = if note_hash.counter() == 0 { + // If counter is zero, the note hash is either empty or is emitted from private and has been siloed in private_kernel_tail_to_public. + note_hash.value() + } else { + silo_note_hash(note_hash, tx_hash, i) + }; + siloed_note_hashes[i] = siloed_note_hash; + if siloed_note_hash != 0 { + siloed_note_hash_hints[i] = SiloedNoteHashHint { siloed_note_hash, index: i }; + } + } + + // Public data. + let combined_writes = array_merge( + previous_kernel.end_non_revertible.public_data_update_requests, + previous_kernel.end.public_data_update_requests + ); + let (public_data_leaves, unique_slot_index_hints) = generate_public_data_leaves( + previous_kernel.validation_requests.public_data_reads, + combined_writes, + public_data_leaf_hints + ); + let (public_data_writes, public_data_linked_index_hints) = generate_overridable_public_data_writes(combined_writes, public_data_leaves); + + OutputHints { + siloed_note_hashes, + siloed_note_hash_hints, + sorted_note_hash_hints: get_combined_order_hints_asc(non_revertible.note_hashes, revertible.note_hashes), + sorted_nullifier_hints: get_combined_order_hints_asc(non_revertible.nullifiers, revertible.nullifiers), + sorted_l2_to_l1_msg_hints: get_combined_order_hints_asc(non_revertible.l2_to_l1_msgs, revertible.l2_to_l1_msgs), + sorted_note_encrypted_log_hash_hints: get_combined_order_hints_asc( + non_revertible.note_encrypted_logs_hashes, + revertible.note_encrypted_logs_hashes + ), + sorted_encrypted_log_hash_hints: get_combined_order_hints_asc( + non_revertible.encrypted_logs_hashes, + revertible.encrypted_logs_hashes + ), + sorted_unencrypted_log_hash_hints: get_combined_order_hints_asc( + non_revertible.unencrypted_logs_hashes, + revertible.unencrypted_logs_hashes + ), + public_data_writes, + public_data_leaves, + unique_slot_index_hints, + public_data_linked_index_hints + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_overridable_public_data_writes.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_overridable_public_data_writes.nr new file mode 100644 index 00000000000..9ecb9d69902 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_overridable_public_data_writes.nr @@ -0,0 +1,58 @@ +use dep::types::{ + abis::{public_data_update_request::PublicDataUpdateRequest, public_data_write::OverridablePublicDataWrite}, + data::OverridablePublicDataTreeLeaf, traits::Empty, utils::arrays::{array_length, find_index_hint} +}; + +struct LinkedIndexHint { + is_first_write: bool, + prev_index: u32, +} + +impl Empty for LinkedIndexHint { + fn empty() -> Self { + LinkedIndexHint { is_first_write: false, prev_index: 0 } + } +} + +unconstrained pub fn generate_overridable_public_data_writes( + public_data_writes: [PublicDataUpdateRequest; NUM_WRITES], + public_data_leaves: [OverridablePublicDataTreeLeaf; NUM_LEAVES] +) -> ([OverridablePublicDataWrite; NUM_WRITES], [LinkedIndexHint; NUM_WRITES]) { + let mut overridable_public_data_writes = [OverridablePublicDataWrite::empty(); NUM_WRITES]; + let mut hints = [LinkedIndexHint::empty(); NUM_WRITES]; + + let writes_len = array_length(public_data_writes); + for i in 0..writes_len { + let write = public_data_writes[i]; + let mut override_counter = 0; + let mut is_first_write = false; + let mut prev_index = 0; + let mut prev_counter = 0; + + for j in 0..writes_len { + let other = public_data_writes[j]; + if (j != i) & (other.leaf_slot == write.leaf_slot) { + if other.counter > write.counter { + if (override_counter == 0) | (other.counter < override_counter) { + override_counter = other.counter; + } + } else if other.counter < write.counter { + if other.counter > prev_counter { + prev_counter = other.counter; + prev_index = j; + } + } + } + } + + if prev_counter == 0 { + is_first_write = true; + prev_index = find_index_hint(public_data_leaves, |leaf: OverridablePublicDataTreeLeaf| leaf.leaf.slot == write.leaf_slot); + } + + overridable_public_data_writes[i] = OverridablePublicDataWrite { write, override_counter }; + hints[i] = LinkedIndexHint { is_first_write, prev_index }; + } + + (overridable_public_data_writes, hints) +} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_public_data_leaves.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_public_data_leaves.nr new file mode 100644 index 00000000000..6df5c91dc6d --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_public_data_leaves.nr @@ -0,0 +1,100 @@ +use dep::types::{ + abis::{public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest}, + data::{OverridablePublicDataTreeLeaf, PublicDataLeafHint, PublicDataTreeLeaf}, traits::Empty, + utils::arrays::{get_sorted_result, SortedResult} +}; + +struct SlotIndex { + slot: Field, + index: u32, + counter: u32, +} + +impl Eq for SlotIndex { + fn eq(self, other: Self) -> bool { + (self.slot == other.slot) & (self.index == other.index) & (self.counter == other.counter) + } +} + +impl Empty for SlotIndex { + fn empty() -> Self { + SlotIndex { slot: 0, index: 0, counter: 0 } + } +} + +fn compare_by_slot_then_index(a: SlotIndex, b: SlotIndex) -> bool { + if a.slot == b.slot { + (a.index == 0) | (b.index > a.index) + } else { + (b.slot == 0) | ((a.slot != 0) & a.slot.lt(b.slot)) + } +} + +fn compare_by_index(a: SlotIndex, b: SlotIndex) -> bool { + (a.slot != 0) & ((b.slot == 0) | (a.index < b.index)) +} + +unconstrained pub fn generate_public_data_leaves( + reads: [PublicDataRead; NUM_READS], + writes: [PublicDataUpdateRequest; NUM_WRITES], + hints: [PublicDataLeafHint; NUM_HINTS] +) -> ([OverridablePublicDataTreeLeaf; NUM_HINTS], SortedResult) { + // Combine reads and writes. The combined data has the slots and original indexes. + // Original indexes for writes are modified to have an offset of NUM_READS, ensuring that writes are placed after reads. + let mut combined_data: BoundedVec = BoundedVec::new(); + for i in 0..reads.len() { + let read = reads[i]; + if read.leaf_slot != 0 { + combined_data.push(SlotIndex { slot: read.leaf_slot, index: i, counter: 0 }); + } + } + for i in 0..writes.len() { + let write = writes[i]; + if write.leaf_slot != 0 { + combined_data.push(SlotIndex { slot: write.leaf_slot, index: i + NUM_READS, counter: write.counter }); + } + } + + // Sort the combined data by slot then index. + // Find the data with unique slots from the sorted result. + let sorted_combined_data = combined_data.storage.sort_via(compare_by_slot_then_index); + let mut prev_slot = 0; + let mut override_counter = 0; + let mut data_with_unique_slot: BoundedVec = BoundedVec::new(); + for i in 0..combined_data.len() { + let data = sorted_combined_data[i]; + if data.slot != prev_slot { + // Found an unique slot. + data_with_unique_slot.push(data); + prev_slot = data.slot; + override_counter = 0; + } + if data.index >= NUM_READS { + // Found a write. + // If it's the first write, update the override_counter of the data with the same slot. + if (override_counter == 0) | (data.counter < override_counter) { + override_counter = data.counter; + data_with_unique_slot.storage[data_with_unique_slot.len() - 1].counter = override_counter; + } + } + } + let sorted_unique_slots = data_with_unique_slot.storage.map(|d: SlotIndex| d.slot); + + // Sort the data by original index. + let mut leaves = [OverridablePublicDataTreeLeaf::empty(); NUM_HINTS]; + let sorted_result = get_sorted_result(data_with_unique_slot.storage, compare_by_index); + for i in 0..data_with_unique_slot.len() { + let sorted = sorted_result.sorted_array[i]; + // The provided hints should've been sorted. + let hint = hints[i]; + let exists = hint.preimage.slot == sorted.slot; + let value = if exists { hint.preimage.value } else { 0 }; + leaves[i] = OverridablePublicDataTreeLeaf { leaf: PublicDataTreeLeaf { slot: sorted.slot, value }, override_counter: sorted.counter }; + } + + (leaves, SortedResult { + sorted_array: sorted_unique_slots, + sorted_index_hints: sorted_result.original_index_hints, // We sort the sorted_unique_slots to get the hints so original_index_hints becomes the sorted_index_hints and vice versa. + original_index_hints: sorted_result.sorted_index_hints + }) +} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator.nr index 2dba886c754..4f6afcd9f52 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator.nr @@ -1,31 +1,46 @@ -mod output_hints; - -use crate::components::public_tail_output_validator::output_hints::{generate_output_hints, OutputHints, SiloedNoteHashHint}; +mod validate_linked_public_data_writes; +mod validate_public_data_leaf_memberships; +mod validate_unique_leaf_slots; + +use crate::components::{ + public_tail_output_validator::{ + validate_linked_public_data_writes::validate_linked_public_data_writes, + validate_public_data_leaf_memberships::validate_public_data_leaf_memberships, + validate_unique_leaf_slots::validate_unique_leaf_slots +}, + public_tail_output_composer::{OutputHints, SiloedNoteHashHint} +}; use dep::types::{ abis::{ kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, - log_hash::{LogHash, ScopedLogHash}, note_hash::{NoteHash, ScopedNoteHash}, nullifier::Nullifier + log_hash::{LogHash, ScopedLogHash}, note_hash::ScopedNoteHash, nullifier::Nullifier, + public_data_update_request::PublicDataUpdateRequest, public_data_write::OverridablePublicDataWrite }, - hash::silo_note_hash, messaging::l2_to_l1_message::ScopedL2ToL1Message, + data::PublicDataLeafHint, hash::silo_note_hash, messaging::l2_to_l1_message::ScopedL2ToL1Message, partial_state_reference::PartialStateReference, - utils::arrays::{array_length, assert_combined_sorted_transformed_value_array_asc, assert_combined_deduped_array} + utils::arrays::{ + assert_combined_sorted_transformed_value_array_asc, assert_combined_transformed_array, + assert_deduped_array +} }; -struct PublicTailOutputValidator { +struct PublicTailOutputValidator { output: KernelCircuitPublicInputs, previous_kernel: PublicKernelCircuitPublicInputs, start_state: PartialStateReference, - hints: OutputHints + hints: OutputHints, + public_data_leaf_hints: [PublicDataLeafHint; NUM_PUBLIC_DATA_LEAVES], } -impl PublicTailOutputValidator { +impl PublicTailOutputValidator { pub fn new( output: KernelCircuitPublicInputs, previous_kernel: PublicKernelCircuitPublicInputs, - start_state: PartialStateReference + start_state: PartialStateReference, + hints: OutputHints, + public_data_leaf_hints: [PublicDataLeafHint; NUM_PUBLIC_DATA_LEAVES] ) -> Self { - let hints = generate_output_hints(previous_kernel, output); - PublicTailOutputValidator { output, previous_kernel, start_state, hints } + PublicTailOutputValidator { output, previous_kernel, start_state, hints, public_data_leaf_hints } } pub fn validate(self) { @@ -139,12 +154,39 @@ impl PublicTailOutputValidator { } fn validate_deduped_public_data_writes(self) { - assert_combined_deduped_array( + validate_public_data_leaf_memberships( + self.hints.public_data_leaves, + self.public_data_leaf_hints, + self.start_state.public_data_tree.root + ); + + // Check that public_data_writes are simply the writes in the two accumulated data arrays combined, + // with override_counter added to each non-empty write as hint. + // override_counter is checked in validate_linked_public_data_writes. + assert_combined_transformed_array( self.previous_kernel.end_non_revertible.public_data_update_requests, self.previous_kernel.end.public_data_update_requests, - self.hints.sorted_public_data_update_requests, - self.output.end.public_data_update_requests, - self.hints.deduped_public_data_update_request_hints + self.hints.public_data_writes, + |from: PublicDataUpdateRequest, to: OverridablePublicDataWrite| to.write == from + ); + + // All non-zero slots in leaves must be unique, ensuring that writes with the same leaf slot are grouped into a single linked list. + validate_unique_leaf_slots( + self.hints.public_data_leaves, + self.hints.unique_slot_index_hints + ); + + // Validate the override_counter of writes, ensuring that they in the correct list in the correct order. + validate_linked_public_data_writes( + self.hints.public_data_writes, + self.hints.public_data_leaves, + self.hints.public_data_linked_index_hints + ); + + // Check that the output contains the last write in each linked list. + assert_deduped_array( + self.hints.public_data_writes, + self.output.end.public_data_update_requests ); } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/output_hints.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/output_hints.nr deleted file mode 100644 index 95d26ece7e2..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/output_hints.nr +++ /dev/null @@ -1,89 +0,0 @@ -use dep::types::{ - abis::{ - kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, - public_data_update_request::PublicDataUpdateRequest -}, - constants::{ - MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - MAX_ENCRYPTED_LOGS_PER_TX -}, - hash::silo_note_hash, traits::Empty, - utils::arrays::{ - array_merge, CombinedOrderHint, DedupedHints, get_combined_order_hints_asc, get_deduped_hints, - sort_by_position_then_counter -} -}; - -struct SiloedNoteHashHint { - siloed_note_hash: Field, - index: u32, -} - -impl Empty for SiloedNoteHashHint { - fn empty() -> Self { - SiloedNoteHashHint { siloed_note_hash: 0, index: 0 } - } -} - -impl Eq for SiloedNoteHashHint { - fn eq(self, other: Self) -> bool { - (self.siloed_note_hash == other.siloed_note_hash) & (self.index == other.index) - } -} - -struct OutputHints { - siloed_note_hash_hints: [SiloedNoteHashHint; MAX_NOTE_HASHES_PER_TX], - sorted_note_hash_hints: [CombinedOrderHint; MAX_NOTE_HASHES_PER_TX], - sorted_nullifier_hints: [CombinedOrderHint; MAX_NULLIFIERS_PER_TX], - sorted_l2_to_l1_msg_hints: [CombinedOrderHint; MAX_L2_TO_L1_MSGS_PER_TX], - sorted_note_encrypted_log_hash_hints: [CombinedOrderHint; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - sorted_encrypted_log_hash_hints: [CombinedOrderHint; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hash_hints: [CombinedOrderHint; MAX_UNENCRYPTED_LOGS_PER_TX], - sorted_public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - deduped_public_data_update_request_hints: DedupedHints, -} - -unconstrained pub fn generate_output_hints( - previous_kernel: PublicKernelCircuitPublicInputs, - output: KernelCircuitPublicInputs -) -> OutputHints { - let non_revertible = previous_kernel.end_non_revertible; - let revertible = previous_kernel.end; - - let mut siloed_note_hash_hints = output.end.note_hashes.map(|siloed_note_hash| SiloedNoteHashHint { siloed_note_hash, index: 0 }); - for i in 0..siloed_note_hash_hints.len() { - if siloed_note_hash_hints[i].siloed_note_hash != 0 { - siloed_note_hash_hints[i].index = i; - } - } - - OutputHints { - siloed_note_hash_hints, - sorted_note_hash_hints: get_combined_order_hints_asc(non_revertible.note_hashes, revertible.note_hashes), - sorted_nullifier_hints: get_combined_order_hints_asc(non_revertible.nullifiers, revertible.nullifiers), - sorted_l2_to_l1_msg_hints: get_combined_order_hints_asc(non_revertible.l2_to_l1_msgs, revertible.l2_to_l1_msgs), - sorted_note_encrypted_log_hash_hints: get_combined_order_hints_asc( - non_revertible.note_encrypted_logs_hashes, - revertible.note_encrypted_logs_hashes - ), - sorted_encrypted_log_hash_hints: get_combined_order_hints_asc( - non_revertible.encrypted_logs_hashes, - revertible.encrypted_logs_hashes - ), - sorted_unencrypted_log_hash_hints: get_combined_order_hints_asc( - non_revertible.unencrypted_logs_hashes, - revertible.unencrypted_logs_hashes - ), - sorted_public_data_update_requests: sort_by_position_then_counter( - array_merge( - non_revertible.public_data_update_requests, - revertible.public_data_update_requests - ) - ), - deduped_public_data_update_request_hints: get_deduped_hints( - non_revertible.public_data_update_requests, - revertible.public_data_update_requests - ) - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/validate_linked_public_data_writes.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/validate_linked_public_data_writes.nr new file mode 100644 index 00000000000..40fcb6415f7 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/validate_linked_public_data_writes.nr @@ -0,0 +1,178 @@ +use crate::components::public_tail_output_composer::LinkedIndexHint; +use dep::types::{abis::public_data_write::OverridablePublicDataWrite, data::OverridablePublicDataTreeLeaf}; + +// Check that each non-empty write is correctly linked to either a leaf or another write. +// All the writes with the same leaf slot will form a single linked list. +// Note that public_data_leaves must be verified to contain unique slots before passing to this function. +pub fn validate_linked_public_data_writes( + public_data_writes: [OverridablePublicDataWrite; NUM_WRITES], + public_data_leaves: [OverridablePublicDataTreeLeaf; NUM_LEAVES], + hints: [LinkedIndexHint; NUM_WRITES] +) { + for i in 0..public_data_writes.len() { + let write = public_data_writes[i]; + let hint = hints[i]; + if write.counter() != 0 { + if hint.is_first_write { + // It's linked to a leaf in the tree. + let data_hint = public_data_leaves[hint.prev_index]; + assert_eq(data_hint.leaf.slot, write.inner().leaf_slot, "hinted leaf has different slot"); + assert_eq( + data_hint.override_counter, write.counter(), "hinted leaf does not link to current write" + ); + } else { + // It's linked to another write for the same leaf slot. + let prev = public_data_writes[hint.prev_index]; + assert_eq(prev.inner().leaf_slot, write.inner().leaf_slot, "hinted write has different slot"); + assert(prev.counter() < write.counter(), "previous write must have a smaller counter"); + assert_eq( + prev.override_counter, write.counter(), "hinted previous write does not link to current write" + ); + } + } + } +} + +mod tests { + use crate::components::{ + public_tail_output_composer::LinkedIndexHint, + public_tail_output_validator::validate_linked_public_data_writes::validate_linked_public_data_writes + }; + use dep::types::{ + abis::{public_data_write::OverridablePublicDataWrite, public_data_update_request::PublicDataUpdateRequest}, + data::{OverridablePublicDataTreeLeaf, PublicDataTreeLeaf}, tests::utils::pad_end + }; + + struct TestBuilder { + public_data_writes: [OverridablePublicDataWrite; 8], + public_data_leaves: [OverridablePublicDataTreeLeaf; 12], + hints: [LinkedIndexHint; 8] + } + + impl TestBuilder { + pub fn new_empty() -> Self { + let public_data_writes = pad_end([], OverridablePublicDataWrite::empty()); + let public_data_leaves = pad_end([], OverridablePublicDataTreeLeaf::empty()); + let hints = pad_end([], LinkedIndexHint::empty()); + TestBuilder { public_data_writes, public_data_leaves, hints } + } + + pub fn new() -> Self { + let public_data_writes = pad_end( + [ + OverridablePublicDataWrite { write: PublicDataUpdateRequest { leaf_slot: 33, new_value: 300, counter: 30 }, override_counter: 0 }, + OverridablePublicDataWrite { write: PublicDataUpdateRequest { leaf_slot: 22, new_value: 202, counter: 40 }, override_counter: 50 }, + OverridablePublicDataWrite { write: PublicDataUpdateRequest { leaf_slot: 11, new_value: 100, counter: 10 }, override_counter: 0 }, + OverridablePublicDataWrite { write: PublicDataUpdateRequest { leaf_slot: 22, new_value: 201, counter: 20 }, override_counter: 40 }, + OverridablePublicDataWrite { write: PublicDataUpdateRequest { leaf_slot: 22, new_value: 203, counter: 50 }, override_counter: 0 } + ], + OverridablePublicDataWrite::empty() + ); + + let public_data_leaves = pad_end( + [ + OverridablePublicDataTreeLeaf { leaf: PublicDataTreeLeaf { slot: 0, value: 0 }, override_counter: 0 }, + OverridablePublicDataTreeLeaf { leaf: PublicDataTreeLeaf { slot: 22, value: 200 }, override_counter: 20 }, + OverridablePublicDataTreeLeaf { leaf: PublicDataTreeLeaf { slot: 44, value: 0 }, override_counter: 0 }, + OverridablePublicDataTreeLeaf { leaf: PublicDataTreeLeaf { slot: 11, value: 0 }, override_counter: 10 }, + OverridablePublicDataTreeLeaf { leaf: PublicDataTreeLeaf { slot: 33, value: 0 }, override_counter: 30 } + ], + OverridablePublicDataTreeLeaf::empty() + ); + + let hints = pad_end( + [ + LinkedIndexHint { is_first_write: true, prev_index: 4 }, + LinkedIndexHint { is_first_write: false, prev_index: 3 }, + LinkedIndexHint { is_first_write: true, prev_index: 3 }, + LinkedIndexHint { is_first_write: true, prev_index: 1 }, + LinkedIndexHint { is_first_write: false, prev_index: 1 } + ], + LinkedIndexHint::empty() + ); + + TestBuilder { public_data_writes, public_data_leaves, hints } + } + + pub fn execute(self) { + validate_linked_public_data_writes(self.public_data_writes, self.public_data_leaves, self.hints); + } + } + + #[test] + fn validate_linked_public_data_writes_empty_succeeds() { + let builder = TestBuilder::new_empty(); + builder.execute(); + } + + #[test] + fn validate_linked_public_data_writes_succeeds() { + let builder = TestBuilder::new(); + builder.execute(); + } + + #[test(should_fail_with="hinted leaf has different slot")] + fn validate_linked_public_data_writes_link_prev_to_empty_leaf_fails() { + let mut builder = TestBuilder::new(); + + // Link the first write to an empty leaf. + builder.hints[0].prev_index = 7; + + builder.execute(); + } + + #[test(should_fail_with="hinted leaf does not link to current write")] + fn validate_linked_public_data_writes_link_two_writes_to_same_leaf_fails() { + let mut builder = TestBuilder::new(); + + // Link the write to a leaf with the same slot. + builder.hints[1] = builder.hints[3]; + + builder.execute(); + } + + #[test(should_fail_with="hinted write has different slot")] + fn validate_linked_public_data_writes_link_prev_to_empty_write_fails() { + let mut builder = TestBuilder::new(); + + // Link the write to an empty write. + builder.hints[1].prev_index = 7; + + builder.execute(); + } + + #[test(should_fail_with="previous write must have a smaller counter")] + fn validate_linked_public_data_writes_not_sorted_by_counter_fails() { + let mut builder = TestBuilder::new(); + + // Change from leaf -> write[3] -> write[1] -> write[4] to leaf -> write[1] -> write[3] -> write[4] + let leaf_index = builder.hints[3].prev_index; + // Link the leaf to the 1st write. + builder.public_data_leaves[leaf_index].override_counter = builder.public_data_writes[1].counter(); + // Link the 1st write to the leaf and the 3rd write. + builder.hints[1].is_first_write = true; + builder.hints[1].prev_index = leaf_index; + builder.public_data_writes[1].override_counter = builder.public_data_writes[3].counter(); + // Link the 3rd write to the 1st write and the 4th write. + builder.hints[3].is_first_write = false; + builder.hints[3].prev_index = 1; + builder.public_data_writes[3].override_counter = builder.public_data_writes[4].counter(); + // Link the 4th write to the 3rd write. + builder.hints[4].prev_index = 3; + + builder.execute(); + } + + #[test(should_fail_with="hinted previous write does not link to current write")] + fn validate_linked_public_data_writes_link_two_writes_to_same_prev_write_fails() { + let mut builder = TestBuilder::new(); + + // Link a write to the previous write of its previous write. + let prev_write_index = builder.hints[4].prev_index; + builder.hints[4].prev_index = 3; + // Clear the counter and link of its previous write. + builder.public_data_writes[prev_write_index].override_counter = 0; + + builder.execute(); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/validate_public_data_leaf_memberships.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/validate_public_data_leaf_memberships.nr new file mode 100644 index 00000000000..1bd7f6b3c2d --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/validate_public_data_leaf_memberships.nr @@ -0,0 +1,35 @@ +use dep::types::{ + data::{OverridablePublicDataTreeLeaf, PublicDataLeafHint}, + merkle_tree::conditionally_assert_check_membership +}; + +// Perform membership check for all non-zero leaf slots, ensuring that the values being read are correct and the public data tree is updated with the correct low leaves. +// TODO: Update public data tree in the tail circuit. Otherwise, change this to just check the leaves for public data reads. +pub fn validate_public_data_leaf_memberships( + leaves: [OverridablePublicDataTreeLeaf; N], + leaf_hints: [PublicDataLeafHint; N], + tree_root: Field +) { + for i in 0..leaves.len() { + let leaf = leaves[i].leaf; + let hint = leaf_hints[i]; + if leaf.slot != 0 { + let exists_in_tree = leaf.slot == hint.preimage.slot; + if exists_in_tree { + assert( + leaf.value == hint.preimage.value, "Hinted public data value does not match the value in leaf preimage" + ); + } else { + assert(leaf.value == 0, "Value must be 0 for non-existent public data"); + } + + conditionally_assert_check_membership( + leaf.slot, + exists_in_tree, + hint.preimage, + hint.membership_witness, + tree_root + ); + } + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/validate_unique_leaf_slots.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/validate_unique_leaf_slots.nr new file mode 100644 index 00000000000..6aa8a79d41f --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_validator/validate_unique_leaf_slots.nr @@ -0,0 +1,157 @@ +use dep::types::{data::OverridablePublicDataTreeLeaf, utils::arrays::SortedResult}; + +// Validate that every non-zero slot in leaves is unique. +pub fn validate_unique_leaf_slots( + leaves: [OverridablePublicDataTreeLeaf; N], + unique_slot_index_hints: SortedResult +) { + let sorted_leaf_slots = unique_slot_index_hints.sorted_array; + let sorted_leaf_slot_indexes = unique_slot_index_hints.sorted_index_hints; + let original_leaf_indexes = unique_slot_index_hints.original_index_hints; + let mut prev_slot = 0; + for i in 0..N { + let leaf = leaves[i].leaf; + let sorted_index = if leaf.slot != 0 { + sorted_leaf_slot_indexes[i] + } else { + i // This ensures that sorted_leaf_slots is padded with the same amount of zero slots as leaves. + }; + let hinted_leaf_slot = sorted_leaf_slots[sorted_index]; + assert_eq(hinted_leaf_slot, leaf.slot, "mismatch hinted slot"); + assert_eq(original_leaf_indexes[sorted_index], i, "sorted value does not link to leaf"); // This ensures that each sorted_leaf_slot can only be refered to once. + + let curr_leaf_alot = sorted_leaf_slots[i]; + if leaf.slot != 0 { + assert(prev_slot.lt(curr_leaf_alot), "hinted slots are not sorted"); // This ensures that all non-zero slots are unique. + } + prev_slot = curr_leaf_alot; + } +} + +mod tests { + use crate::components::public_tail_output_validator::validate_unique_leaf_slots::validate_unique_leaf_slots; + use dep::types::{ + data::{OverridablePublicDataTreeLeaf, PublicDataTreeLeaf}, tests::utils::pad_end, + utils::arrays::SortedResult + }; + + global NUM_TEST_LEAVES = 10; + + struct TestBuilder { + leaves: [OverridablePublicDataTreeLeaf; NUM_TEST_LEAVES], + sorted_array: [Field; NUM_TEST_LEAVES], + sorted_index_hints: [u32; NUM_TEST_LEAVES], + original_index_hints: [u32; NUM_TEST_LEAVES], + } + + impl TestBuilder { + pub fn new() -> Self { + let leaves = pad_end([], OverridablePublicDataTreeLeaf::empty()); + let sorted_array = pad_end([], 0); + let sorted_index_hints = pad_end([], 0); + let mut original_index_hints = pad_end([], 0); + for i in 0..original_index_hints.len() { + original_index_hints[i] = i; + } + TestBuilder { leaves, sorted_array, sorted_index_hints, original_index_hints } + } + + pub fn update_leaves(&mut self, slots: [Field; N]) { + let leaves = slots.map( + |slot: Field| OverridablePublicDataTreeLeaf { leaf: PublicDataTreeLeaf { slot, value: 1 }, override_counter: 0 } + ); + self.leaves = pad_end(leaves, OverridablePublicDataTreeLeaf::empty()); + } + + pub fn update_sorted_array(&mut self, sorted_values: [Field; N]) { + self.sorted_array = pad_end(sorted_values, 0); + } + + pub fn update_sorted_index_hints(&mut self, sorted_indexes: [u32; N]) { + self.sorted_index_hints = pad_end(sorted_indexes, 0); + } + + pub fn update_original_index_hints(&mut self, original_indexes: [u32; N]) { + let mut original_index_hints = pad_end(original_indexes, 0); + for i in original_indexes.len()..original_index_hints.len() { + original_index_hints[i] = i; + } + self.original_index_hints = original_index_hints; + } + + pub fn execute(self) { + let hints = SortedResult { + sorted_array: self.sorted_array, + sorted_index_hints: self.sorted_index_hints, + original_index_hints: self.original_index_hints + }; + validate_unique_leaf_slots(self.leaves, hints); + } + } + + #[test] + fn validate_unique_leaf_slots_empty_succeeds() { + let builder = TestBuilder::new(); + builder.execute() + } + + #[test] + fn validate_unique_leaf_slots_succeeds() { + let mut builder = TestBuilder::new(); + + builder.update_leaves([22, 44, 33, 11]); + builder.update_sorted_array([11, 22, 33, 44]); + builder.update_sorted_index_hints([1, 3, 2, 0]); + builder.update_original_index_hints([3, 0, 2, 1]); + + builder.execute() + } + + #[test(should_fail_with="sorted value does not link to leaf")] + fn validate_unique_leaf_slots_duplicates_remove_hint_fails() { + let mut builder = TestBuilder::new(); + + builder.update_leaves([22, 11, 11]); + builder.update_sorted_array([11, 22]); + builder.update_sorted_index_hints([1, 0, 0]); + builder.update_original_index_hints([1, 0]); + + builder.execute() + } + + #[test(should_fail_with="hinted slots are not sorted")] + fn validate_unique_leaf_slots_duplicates_extra_hint_fails() { + let mut builder = TestBuilder::new(); + + builder.update_leaves([22, 11, 11]); + builder.update_sorted_array([11, 11, 22]); + builder.update_sorted_index_hints([2, 0, 1]); + builder.update_original_index_hints([1, 2, 0]); + + builder.execute() + } + + #[test(should_fail_with="hinted slots are not sorted")] + fn validate_unique_leaf_slots_duplicates_extra_hint_in_padded_first_zero_fails() { + let mut builder = TestBuilder::new(); + + builder.update_leaves([22, 11, 11]); + builder.update_sorted_array([0, 11, 22, 0, 11]); // The first zero slot triggers the assert. + builder.update_sorted_index_hints([2, 1, 4]); + builder.update_original_index_hints([3, 1, 0, 4, 2]); + + builder.execute() + } + + #[test(should_fail_with="mismatch hinted slot")] + fn validate_unique_leaf_slots_duplicates_extra_hint_in_padded_first_non_zero_fails() { + let mut builder = TestBuilder::new(); + + builder.update_leaves([22, 11, 11]); + builder.update_sorted_array([1, 11, 22, 0, 11]); // Change the first slot to be non-zero. + builder.update_sorted_index_hints([2, 1, 4]); + builder.update_original_index_hints([3, 1, 0, 3, 2]); + + builder.execute() + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/lib.nr index 164d717ea3a..a090565150f 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/lib.nr @@ -5,7 +5,7 @@ mod public_kernel_app_logic; mod public_kernel_teardown; mod public_kernel_tail; -use public_kernel_setup::PublicKernelSetupCircuitPrivateInputs; -use public_kernel_app_logic::PublicKernelAppLogicCircuitPrivateInputs; -use public_kernel_teardown::PublicKernelTeardownCircuitPrivateInputs; -use public_kernel_tail::PublicKernelTailCircuitPrivateInputs; +pub use public_kernel_setup::PublicKernelSetupCircuitPrivateInputs; +pub use public_kernel_app_logic::PublicKernelAppLogicCircuitPrivateInputs; +pub use public_kernel_teardown::PublicKernelTeardownCircuitPrivateInputs; +pub use public_kernel_tail::PublicKernelTailCircuitPrivateInputs; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index 7f6b5f4e93b..7e059aa7fd3 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -50,13 +50,11 @@ mod tests { use dep::types::{ abis::{ gas::Gas, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - note_hash::{NoteHash, ScopedNoteHash}, log_hash::ScopedLogHash, nullifier::{Nullifier, ScopedNullifier}, public_call_stack_item_compressed::PublicCallStackItemCompressed, - public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, - read_request::ReadRequest + public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest }, - constants::{PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, PUBLIC_KERNEL_APP_LOGIC_INDEX, BASE_ROLLUP_INDEX}, + constants::{PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, PUBLIC_KERNEL_APP_LOGIC_INDEX}, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, address::AztecAddress, hash::compute_siloed_nullifier, tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq}, traits::is_empty diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr index 793f9083f0c..4dee42f6364 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr @@ -59,12 +59,11 @@ mod tests { abis::{ function_selector::FunctionSelector, gas::Gas, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, max_block_number::MaxBlockNumber, - note_hash::NoteHash, public_call_stack_item_compressed::PublicCallStackItemCompressed, + public_call_stack_item_compressed::PublicCallStackItemCompressed, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, - public_call_data::PublicCallData, public_kernel_data::PublicKernelData, read_request::ReadRequest }, - address::AztecAddress, constants::{PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, BASE_ROLLUP_INDEX}, + address::AztecAddress, constants::PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq}, traits::is_empty }; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index 68c39dbf448..d44aa614db4 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -1,23 +1,25 @@ use crate::{ components::{ previous_kernel_validator::PreviousKernelValidator, - public_tail_output_composer::PublicTailOutputComposer, + public_tail_output_composer::{OutputHints, PublicTailOutputComposer}, public_tail_output_validator::PublicTailOutputValidator }, public_kernel_phase::PublicKernelPhase }; use dep::reset_kernel_lib::{ - NullifierReadRequestHints, NullifierNonExistentReadRequestHints, PublicDataReadRequestHints, - PublicValidationRequestProcessor, TreeLeafReadRequestHint + NullifierReadRequestHints, NullifierNonExistentReadRequestHints, PublicValidationRequestProcessor, + public_data_read_request_hints::{build_public_data_read_request_hints, PublicDataReadRequestHints}, + TreeLeafReadRequestHint }; use dep::types::{ abis::{kernel_circuit_public_inputs::KernelCircuitPublicInputs, public_kernel_data::PublicKernelData}, constants::{ - L1_TO_L2_MSG_TREE_HEIGHT, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_HINTS, - MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, NOTE_HASH_TREE_HEIGHT, - PUBLIC_KERNEL_SETUP_INDEX, PUBLIC_KERNEL_APP_LOGIC_INDEX, PUBLIC_KERNEL_TEARDOWN_INDEX + L1_TO_L2_MSG_TREE_HEIGHT, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_HINTS, MAX_PUBLIC_DATA_READS_PER_TX, + NOTE_HASH_TREE_HEIGHT, PUBLIC_KERNEL_SETUP_INDEX, PUBLIC_KERNEL_APP_LOGIC_INDEX, + PUBLIC_KERNEL_TEARDOWN_INDEX }, - data::public_data_hint::PublicDataHint, partial_state_reference::PartialStateReference + data::PublicDataLeafHint, partial_state_reference::PartialStateReference }; global ALLOWED_PREVIOUS_CIRCUITS = [ @@ -32,14 +34,25 @@ struct PublicKernelTailCircuitPrivateInputs { nullifier_read_request_hints: NullifierReadRequestHints, nullifier_non_existent_read_request_hints: NullifierNonExistentReadRequestHints, l1_to_l2_msg_read_request_hints: [TreeLeafReadRequestHint; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX], - public_data_hints: [PublicDataHint; MAX_PUBLIC_DATA_HINTS], - public_data_read_request_hints: PublicDataReadRequestHints, + public_data_hints: [PublicDataLeafHint; MAX_PUBLIC_DATA_HINTS], start_state: PartialStateReference, } impl PublicKernelTailCircuitPrivateInputs { - unconstrained fn generate_output(self) -> KernelCircuitPublicInputs { - PublicTailOutputComposer::new(self.previous_kernel.public_inputs, self.start_state).finish() + unconstrained fn generate_output_and_hints(self) -> (KernelCircuitPublicInputs, OutputHints, PublicDataReadRequestHints) { + let (output, output_hints) = PublicTailOutputComposer::new( + self.previous_kernel.public_inputs, + self.start_state, + self.public_data_hints + ).finish(); + + let public_data_read_request_hints = build_public_data_read_request_hints( + self.previous_kernel.public_inputs.validation_requests.public_data_reads, + output_hints.public_data_writes, + output_hints.public_data_leaves + ); + + (output, output_hints, public_data_read_request_hints) } pub fn execute(self) -> KernelCircuitPublicInputs { @@ -47,67 +60,73 @@ impl PublicKernelTailCircuitPrivateInputs { previous_kernel_validator.validate_phase(PublicKernelPhase.TAIL); previous_kernel_validator.validate_proof(ALLOWED_PREVIOUS_CIRCUITS); - let previous_public_inputs = self.previous_kernel.public_inputs; + let (output, output_hints, public_data_read_request_hints) = unsafe { + self.generate_output_and_hints() + }; + PublicValidationRequestProcessor::new( - previous_public_inputs, + self.previous_kernel.public_inputs, self.start_state, self.note_hash_read_request_hints, self.nullifier_read_request_hints, self.nullifier_non_existent_read_request_hints, self.l1_to_l2_msg_read_request_hints, - self.public_data_read_request_hints, - self.public_data_hints + output_hints.public_data_writes, + output_hints.public_data_leaves, + public_data_read_request_hints ).validate(); - let output = self.generate_output(); - - PublicTailOutputValidator::new(output, previous_public_inputs, self.start_state).validate(); + PublicTailOutputValidator::new( + output, + self.previous_kernel.public_inputs, + self.start_state, + output_hints, + self.public_data_hints + ).validate(); output } } mod tests { - use crate::{public_kernel_tail::{ALLOWED_PREVIOUS_CIRCUITS, PublicKernelTailCircuitPrivateInputs}}; + use crate::{public_kernel_tail::PublicKernelTailCircuitPrivateInputs}; use dep::reset_kernel_lib::{ tests::{ nullifier_non_existent_read_request_hints_builder::NullifierNonExistentReadRequestHintsBuilder, - nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder, - public_data_read_request_hints_builder::PublicDataReadRequestHintsBuilder + nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder }, - PublicDataHint, reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus}, + reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus}, TreeLeafReadRequestHint }; use dep::types::{ abis::{ - kernel_circuit_public_inputs::KernelCircuitPublicInputs, public_kernel_data::PublicKernelData, - nullifier::ScopedNullifier, nullifier_leaf_preimage::NullifierLeafPreimage + kernel_circuit_public_inputs::KernelCircuitPublicInputs, nullifier::ScopedNullifier, + nullifier_leaf_preimage::NullifierLeafPreimage, + public_data_update_request::PublicDataUpdateRequest }, address::AztecAddress, constants::{ L1_TO_L2_MSG_TREE_HEIGHT, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_HINTS, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - NOTE_HASH_SUBTREE_HEIGHT, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, - NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_HEIGHT, - PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT, MAX_ENCRYPTED_LOGS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - NOTE_HASH_TREE_HEIGHT, PUBLIC_KERNEL_APP_LOGIC_INDEX, BASE_ROLLUP_INDEX, - PUBLIC_KERNEL_SETUP_INDEX, PUBLIC_KERNEL_TEARDOWN_INDEX + MAX_PUBLIC_DATA_HINTS, NOTE_HASH_SUBTREE_HEIGHT, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, + NULLIFIER_TREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT, + PUBLIC_DATA_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTE_HASH_TREE_HEIGHT, + PUBLIC_KERNEL_APP_LOGIC_INDEX, PUBLIC_KERNEL_SETUP_INDEX, PUBLIC_KERNEL_TEARDOWN_INDEX }, + data::{PublicDataLeafHint, PublicDataTreeLeafPreimage}, hash::{compute_siloed_nullifier, silo_note_hash}, - public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, tests::{ fixture_builder::FixtureBuilder, merkle_tree_utils::NonEmptyMerkleTree, utils::{assert_array_eq, pad_end, swap_items} }, traits::is_empty, partial_state_reference::PartialStateReference, - utils::arrays::{array_length, array_merge}, merkle_tree::MembershipWitness + utils::arrays::{array_merge, find_index_hint}, merkle_tree::MembershipWitness }; - fn build_note_hash_tree(pre_existing_note_hashes: [Field; N]) -> NonEmptyMerkleTree { + fn build_note_hash_tree(leaf_preimages: [Field; N]) -> NonEmptyMerkleTree { NonEmptyMerkleTree::new( - pad_end(pre_existing_note_hashes, 0), + pad_end(leaf_preimages, 0), [0; NOTE_HASH_TREE_HEIGHT], [0; NOTE_HASH_TREE_HEIGHT - NOTE_HASH_SUBTREE_HEIGHT], [0; NOTE_HASH_SUBTREE_HEIGHT] @@ -126,18 +145,12 @@ mod tests { ) } - fn get_settled_public_data_leaves() -> [PublicDataTreeLeafPreimage; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] { - let mut settled_public_data_leaves = [PublicDataTreeLeafPreimage::empty(); MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]; - settled_public_data_leaves[0] = PublicDataTreeLeafPreimage { slot: 22, value: 200, next_slot: 33, next_index: 1 }; - settled_public_data_leaves[1] = PublicDataTreeLeafPreimage { slot: 33, value: 300, next_slot: 0, next_index: 0 }; - settled_public_data_leaves[2] = PublicDataTreeLeafPreimage { slot: 11, value: 100, next_slot: 22, next_index: 0 }; - settled_public_data_leaves - } - - fn build_public_data_tree() -> NonEmptyMerkleTree { - let settled_public_data_leaves = get_settled_public_data_leaves(); + fn build_public_data_tree(leaf_preimages: [PublicDataTreeLeafPreimage; N]) -> NonEmptyMerkleTree { NonEmptyMerkleTree::new( - settled_public_data_leaves.map(|preimage: PublicDataTreeLeafPreimage| preimage.hash()), + pad_end( + leaf_preimages.map(|preimage: PublicDataTreeLeafPreimage| preimage.hash()), + 0 + ), [0; PUBLIC_DATA_TREE_HEIGHT], [0; PUBLIC_DATA_TREE_HEIGHT - PUBLIC_DATA_SUBTREE_HEIGHT], [0; PUBLIC_DATA_SUBTREE_HEIGHT] @@ -150,17 +163,16 @@ mod tests { note_hash_read_request_hints: BoundedVec, MAX_NOTE_HASH_READ_REQUESTS_PER_TX>, nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder, nullifier_non_existent_read_request_hints_builder: NullifierNonExistentReadRequestHintsBuilder, - public_data_read_request_hints_builder: PublicDataReadRequestHintsBuilder, - public_data_hints: BoundedVec, - public_data_tree: NonEmptyMerkleTree, l1_to_l2_msg_read_request_hints: BoundedVec, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX>, - start_state: PartialStateReference, note_hash_tree: NonEmptyMerkleTree, - pre_existing_note_hashes: [Field; 2], + note_hash_leaf_preimages: [Field; 2], + public_data_tree: NonEmptyMerkleTree, + public_data_leaf_preimages: [PublicDataTreeLeafPreimage; 6], + start_state: PartialStateReference, } impl PublicKernelTailCircuitPrivateInputsBuilder { - pub fn new() -> Self { + pub fn new() -> PublicKernelTailCircuitPrivateInputsBuilder { let previous_kernel = FixtureBuilder::new().in_vk_tree(PUBLIC_KERNEL_APP_LOGIC_INDEX); let previous_revertible = FixtureBuilder::new(); let nullifier_non_existent_read_request_hints_builder = NullifierNonExistentReadRequestHintsBuilder::new(); @@ -171,18 +183,17 @@ mod tests { note_hash_read_request_hints: BoundedVec::new(), nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(), nullifier_non_existent_read_request_hints_builder, - public_data_read_request_hints_builder: PublicDataReadRequestHintsBuilder::new(MAX_PUBLIC_DATA_READS_PER_TX), - public_data_hints: BoundedVec::new(), - public_data_tree: NonEmptyMerkleTree::empty(), l1_to_l2_msg_read_request_hints: BoundedVec::new(), - start_state: PartialStateReference::empty(), note_hash_tree: NonEmptyMerkleTree::empty(), - pre_existing_note_hashes: [598589, 714714] + note_hash_leaf_preimages: [598589, 714714], + public_data_tree: NonEmptyMerkleTree::empty(), + public_data_leaf_preimages: pad_end([], PublicDataTreeLeafPreimage::empty()), + start_state: PartialStateReference::empty() } } pub fn with_note_hash_tree(&mut self) -> Self { - self.note_hash_tree = build_note_hash_tree(self.pre_existing_note_hashes); + self.note_hash_tree = build_note_hash_tree(self.note_hash_leaf_preimages); self.start_state.note_hash_tree.root = self.note_hash_tree.get_root(); self.previous_kernel.historical_header.state.partial.note_hash_tree.root = 11111; *self @@ -197,18 +208,25 @@ mod tests { } pub fn with_public_data_tree(&mut self) -> Self { - let public_data_tree = build_public_data_tree(); + let public_data_leaf_preimages = [ + PublicDataTreeLeafPreimage { slot: 0, value: 0, next_slot: 1111, next_index: 3 }, + PublicDataTreeLeafPreimage { slot: 2222, value: 200, next_slot: 3333, next_index: 2 }, + PublicDataTreeLeafPreimage { slot: 3333, value: 300, next_slot: 0, next_index: 0 }, + PublicDataTreeLeafPreimage { slot: 1111, value: 100, next_slot: 2222, next_index: 1 } + ]; + let public_data_tree = build_public_data_tree(public_data_leaf_preimages); + self.public_data_leaf_preimages = pad_end(public_data_leaf_preimages, PublicDataTreeLeafPreimage::empty()); self.public_data_tree = public_data_tree; self.start_state.public_data_tree.root = public_data_tree.get_root(); *self } - pub fn add_note_hash_read_request(&mut self, pre_existing_note_hash_index: u32) { + pub fn add_note_hash_read_request(&mut self, leaf_index: u32) { self.previous_kernel.add_note_hash_tree_leaf_read_requests( - self.pre_existing_note_hashes[pre_existing_note_hash_index], - pre_existing_note_hash_index as Field + self.note_hash_leaf_preimages[leaf_index], + leaf_index as Field ); - let sibling_path = self.note_hash_tree.get_sibling_path(pre_existing_note_hash_index); + let sibling_path = self.note_hash_tree.get_sibling_path(leaf_index); self.note_hash_read_request_hints.push(TreeLeafReadRequestHint { sibling_path }); } @@ -267,35 +285,44 @@ mod tests { self.nullifier_non_existent_read_request_hints_builder.add_value_read(siloed_nullifier); } - pub fn add_public_data_hint_for_settled_public_data(&mut self, leaf_index: u32) { - let leaf_preimage = get_settled_public_data_leaves()[leaf_index]; - let membership_witness = MembershipWitness { leaf_index: leaf_index as Field, sibling_path: self.public_data_tree.get_sibling_path(leaf_index) }; - let hint = PublicDataHint { - leaf_slot: leaf_preimage.slot, - value: leaf_preimage.value, - override_counter: 0, - membership_witness, - leaf_preimage + fn create_public_data_leaf_hint(&mut self, leaf_slot: Field) -> PublicDataLeafHint { + let low_leaf_index = unsafe { + find_index_hint( + self.public_data_leaf_preimages, + |p: PublicDataTreeLeafPreimage| !leaf_slot.lt(p.slot) & (p.next_slot.eq(0) | leaf_slot.lt(p.next_slot)) + ) }; - self.public_data_hints.push(hint); - } - pub fn add_public_data_hint_for_non_existent_public_data(&mut self, leaf_slot: Field, low_leaf_index: u32) { - let leaf_preimage = get_settled_public_data_leaves()[low_leaf_index]; + let preimage = self.public_data_leaf_preimages[low_leaf_index]; let membership_witness = MembershipWitness { leaf_index: low_leaf_index as Field, sibling_path: self.public_data_tree.get_sibling_path(low_leaf_index) }; - let hint = PublicDataHint { leaf_slot, value: 0, override_counter: 0, membership_witness, leaf_preimage }; - self.public_data_hints.push(hint); + + PublicDataLeafHint { preimage, membership_witness } } - pub fn add_pending_public_data_read_request(&mut self, public_date_update_request_index: u32) { - let read_request_index = self.previous_kernel.add_read_request_for_pending_public_data(public_date_update_request_index); - let hint_index = self.public_data_read_request_hints_builder.pending_read_hints.len(); - let hint = PendingReadHint { read_request_index, pending_value_index: public_date_update_request_index }; - self.public_data_read_request_hints_builder.pending_read_hints.push(hint); - self.public_data_read_request_hints_builder.read_request_statuses[read_request_index] = ReadRequestStatus { state: ReadRequestState.PENDING, hint_index }; + fn generate_public_data_leaf_hints(&mut self) -> [PublicDataLeafHint; MAX_PUBLIC_DATA_HINTS] { + let mut public_data_hints = BoundedVec::new(); + let mut unique_slots: BoundedVec = BoundedVec::new(); + + for i in 0..self.previous_kernel.public_data_reads.len() { + let read = self.previous_kernel.public_data_reads.get(i); + if !unique_slots.any(|s| s == read.leaf_slot) { + public_data_hints.push(self.create_public_data_leaf_hint(read.leaf_slot)); + unique_slots.push(read.leaf_slot); + } + } + + for i in 0..self.previous_kernel.public_data_update_requests.len() { + let write = self.previous_kernel.public_data_update_requests.get(i); + if !unique_slots.any(|s| s == write.leaf_slot) { + public_data_hints.push(self.create_public_data_leaf_hint(write.leaf_slot)); + unique_slots.push(write.leaf_slot); + } + } + + public_data_hints.storage } fn sync_counters(&mut self) { @@ -313,15 +340,23 @@ mod tests { previous_kernel.public_inputs.end = self.previous_revertible.to_public_accumulated_data(); self.set_nullifiers_for_non_existent_read_request_hints(); + let public_data_hints = self.generate_public_data_leaf_hints(); + + let nullifier_read_request_hints = unsafe { + self.nullifier_read_request_hints_builder.to_hints() + }; + + let nullifier_non_existent_read_request_hints = unsafe { + self.nullifier_non_existent_read_request_hints_builder.to_hints() + }; let kernel = PublicKernelTailCircuitPrivateInputs { previous_kernel, - nullifier_read_request_hints: self.nullifier_read_request_hints_builder.to_hints(), - nullifier_non_existent_read_request_hints: self.nullifier_non_existent_read_request_hints_builder.to_hints(), - public_data_hints: self.public_data_hints.storage, - public_data_read_request_hints: self.public_data_read_request_hints_builder.to_hints(), note_hash_read_request_hints: self.note_hash_read_request_hints.storage, + nullifier_read_request_hints, + nullifier_non_existent_read_request_hints, l1_to_l2_msg_read_request_hints: self.l1_to_l2_msg_read_request_hints.storage, + public_data_hints, start_state: self.start_state }; @@ -345,7 +380,7 @@ mod tests { } #[test] - fn measuring_of_log_lengths() { + unconstrained fn measuring_of_log_lengths() { let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); // Logs for the previous call stack. let prev_encrypted_logs_hash = 80; @@ -467,90 +502,52 @@ mod tests { } #[test] - unconstrained fn validate_public_data_hints() { + unconstrained fn public_data_reads_and_writes_succeeds() { let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new().with_public_data_tree(); - builder.add_public_data_hint_for_settled_public_data(1); - builder.add_public_data_hint_for_settled_public_data(0); - builder.add_public_data_hint_for_settled_public_data(2); + builder.previous_kernel.add_public_data_read_request(22, 0); - builder.succeeded(); - } + builder.previous_kernel.add_public_data_update_request(11, 500); + builder.previous_kernel.add_public_data_update_request(22, 700); - #[test(should_fail_with="Hinted public data value does not match the value in leaf preimage")] - unconstrained fn validate_public_data_hints_failed_mismatch_value() { - let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new().with_public_data_tree(); + builder.previous_kernel.add_public_data_read_request(22, 700); + builder.previous_kernel.add_public_data_read_request(11, 500); + builder.previous_kernel.add_public_data_read_request(3333, 300); - builder.add_public_data_hint_for_settled_public_data(1); + // Override the previous value at leaf slot 22. + builder.previous_kernel.add_public_data_update_request(22, 701); - let mut hint = builder.public_data_hints.pop(); - hint.value += 1; - builder.public_data_hints.push(hint); + // Override the value of the leaf. + builder.previous_kernel.add_public_data_update_request(3333, 301); - builder.failed(); - } + // Read the new values. + builder.previous_kernel.add_public_data_read_request(22, 701); + builder.previous_kernel.add_public_data_read_request(3333, 301); - #[test] - unconstrained fn validate_public_data_hints_uninitialized_value() { - let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new().with_public_data_tree(); + let prev_writes = builder.previous_kernel.public_data_update_requests.storage; - builder.add_public_data_hint_for_non_existent_public_data(25, 0); + // Shuffle the items so that they are not sorted by counter. + swap_items(&mut builder.previous_kernel.public_data_update_requests, 0, 3); + swap_items(&mut builder.previous_kernel.public_data_update_requests, 1, 3); + swap_items(&mut builder.previous_kernel.public_data_reads, 1, 4); + swap_items(&mut builder.previous_kernel.public_data_reads, 0, 3); - builder.succeeded(); + let public_inputs = builder.execute(); + assert_array_eq( + public_inputs.end.public_data_update_requests, + [ + PublicDataUpdateRequest { leaf_slot: 3333, new_value: 301, counter: prev_writes[4].counter }, + PublicDataUpdateRequest { leaf_slot: 11, new_value: 500, counter: prev_writes[1].counter }, + PublicDataUpdateRequest { leaf_slot: 22, new_value: 701, counter: prev_writes[3].counter } + ] + ); } - #[test(should_fail_with="Value must be 0 for non-existent public data")] - unconstrained fn validate_public_data_hints_failed_non_zero_uninitialized_value() { + #[test(should_fail_with="value in OverridablePublicDataTreeLeaf does not match read request")] + unconstrained fn reading_uninitialized_public_data_non_zero_value_fails() { let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new().with_public_data_tree(); - builder.add_public_data_hint_for_non_existent_public_data(25, 0); - - let mut hint = builder.public_data_hints.pop(); - hint.value = 1; - builder.public_data_hints.push(hint); - - builder.failed(); - } - - #[test] - unconstrained fn pending_public_data_read_requests() { - let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); - - builder.previous_kernel.append_public_data_update_requests(3); - - builder.add_pending_public_data_read_request(1); - builder.add_pending_public_data_read_request(0); - builder.add_pending_public_data_read_request(2); - - builder.succeeded(); - } - - #[test(should_fail_with="Hinted slot of data write does not match read request")] - unconstrained fn pending_public_data_read_requests_failed_wrong_write_index() { - let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); - - builder.previous_kernel.append_public_data_update_requests(2); - - builder.add_pending_public_data_read_request(1); - - let mut hint = builder.public_data_read_request_hints_builder.pending_read_hints.pop(); - hint.pending_value_index += 1; - builder.public_data_read_request_hints_builder.pending_read_hints.push(hint); - - builder.failed(); - } - - #[test(should_fail_with="Hinted value of data write does not match read request")] - unconstrained fn pending_public_data_read_requests_failed_wrong_write_value() { - let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); - - builder.previous_kernel.append_public_data_update_requests(1); - - builder.add_pending_public_data_read_request(0); - - let mut public_data_write = builder.previous_kernel.public_data_update_requests.pop(); - public_data_write.new_value += 1; - builder.previous_kernel.public_data_update_requests.push(public_data_write); + builder.previous_kernel.add_public_data_read_request(1234, 1); builder.failed(); } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr index 84be93df240..087efbf91e7 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr @@ -57,7 +57,7 @@ mod tests { kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, public_call_stack_item_compressed::PublicCallStackItemCompressed }, - address::AztecAddress, constants::{PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, BASE_ROLLUP_INDEX}, + address::AztecAddress, constants::PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq}, traits::is_empty }; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr index 319f2100ddd..7e2624a7fae 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr @@ -1,21 +1,19 @@ -use note_hash_read_request_reset::NoteHashReadRequestHints; -use nullifier_non_existent_read_request_reset::NullifierNonExistentReadRequestHints; -use nullifier_read_request_reset::NullifierReadRequestHints; -use private_validation_request_processor::PrivateValidationRequestProcessor; -use public_data_read_request_reset::PublicDataReadRequestHints; -use public_validation_request_processor::PublicValidationRequestProcessor; -use reset::{ - key_validation_hint::KeyValidationHint, - transient_data::{TransientDataIndexHint, verify_squashed_transient_data}, - tree_leaf_read_request::TreeLeafReadRequestHint -}; -use dep::types::data::public_data_hint::PublicDataHint; - mod note_hash_read_request_reset; mod nullifier_non_existent_read_request_reset; mod nullifier_read_request_reset; mod private_validation_request_processor; -mod public_data_read_request_reset; +mod public_data_read_request_hints; mod public_validation_request_processor; mod reset; mod tests; + +pub use note_hash_read_request_reset::NoteHashReadRequestHints; +pub use nullifier_non_existent_read_request_reset::NullifierNonExistentReadRequestHints; +pub use nullifier_read_request_reset::NullifierReadRequestHints; +pub use private_validation_request_processor::PrivateValidationRequestProcessor; +pub use public_validation_request_processor::PublicValidationRequestProcessor; +pub use reset::{ + key_validation_hint::KeyValidationHint, + transient_data::{TransientDataIndexHint, verify_squashed_transient_data}, + tree_leaf_read_request::TreeLeafReadRequestHint +}; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr index 9b556268a3f..8c53b9be7de 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr @@ -150,13 +150,15 @@ mod tests { (hints, tree_root) } - pub fn get_unverified_read_requests(self) -> [ScopedReadRequest; READ_REQUEST_LEN] { + unconstrained pub fn get_unverified_read_requests(self) -> [ScopedReadRequest; READ_REQUEST_LEN] { get_unverified_read_requests(self.read_requests, self.read_request_statuses) } pub fn verify(self) { let (settled_hints, tree_root) = self.get_settled_read_hints(); - let unverified_read_requests = self.get_unverified_read_requests(); + let unverified_read_requests = unsafe { + self.get_unverified_read_requests() + }; verify_reset_read_requests( self.read_requests, self.pending_values, @@ -173,7 +175,9 @@ mod tests { fn verify_reset_note_hash_read_requests_clears_all_succeeds() { let builder = TestBuilder::new(); - let unverified_read_requests = builder.get_unverified_read_requests(); + let unverified_read_requests = unsafe { + builder.get_unverified_read_requests() + }; assert(is_empty_array(unverified_read_requests)); builder.verify(); @@ -187,7 +191,9 @@ mod tests { builder.read_request_statuses[4] = ReadRequestStatus::empty(); let read_requests = builder.read_requests; - let unverified_read_requests = builder.get_unverified_read_requests(); + let unverified_read_requests = unsafe { + builder.get_unverified_read_requests() + }; assert_array_eq( unverified_read_requests, [read_requests[2], read_requests[4]] diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr index 135099aa541..1f9088af5f5 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr @@ -115,7 +115,6 @@ mod tests { } impl TestBuilder { - fn build_tree(self) -> NonEmptyMerkleTree<2, NULLIFIER_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT - 1, 1> { NonEmptyMerkleTree::new( [self.leaf_preimages[0].hash(), self.leaf_preimages[1].hash()], @@ -143,13 +142,15 @@ mod tests { (hints, tree_root) } - pub fn get_unverified_read_requests(self) -> [ScopedReadRequest; READ_REQUEST_LEN] { + unconstrained pub fn get_unverified_read_requests(self) -> [ScopedReadRequest; READ_REQUEST_LEN] { get_unverified_read_requests(self.read_requests, self.read_request_statuses) } pub fn verify(self) { let (settled_hints, tree_root) = self.get_settled_read_hints(); - let unverified_read_requests = self.get_unverified_read_requests(); + let unverified_read_requests = unsafe { + self.get_unverified_read_requests() + }; verify_reset_read_requests( self.read_requests, self.pending_values, @@ -166,7 +167,9 @@ mod tests { fn verify_reset_nullifier_read_requests_clears_all_succeeds() { let builder = TestBuilder::new(); - let unverified_read_requests = builder.get_unverified_read_requests(); + let unverified_read_requests = unsafe { + builder.get_unverified_read_requests() + }; assert(is_empty_array(unverified_read_requests)); builder.verify(); @@ -180,7 +183,9 @@ mod tests { builder.read_request_statuses[4] = ReadRequestStatus::empty(); let read_requests = builder.read_requests; - let unverified_read_requests = builder.get_unverified_read_requests(); + let unverified_read_requests = unsafe { + builder.get_unverified_read_requests() + }; assert_array_eq( unverified_read_requests, [read_requests[2], read_requests[4]] diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr index 2790cd1dc3e..42a49a84ebc 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr @@ -28,7 +28,7 @@ impl< let NLL_RR_SETTLED: u32, let KEY_VALIDATION_REQUESTS: u32 > PrivateValidationRequestProcessor { - pub fn compose(self) -> PrivateValidationRequests { + unconstrained pub fn compose(self) -> PrivateValidationRequests { let note_hash_read_requests = get_unverified_read_requests( self.validation_requests.note_hash_read_requests, self.note_hash_read_request_hints.read_request_statuses diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_data_read_request_hints.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_data_read_request_hints.nr new file mode 100644 index 00000000000..3f1eebc06cc --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_data_read_request_hints.nr @@ -0,0 +1,50 @@ +use crate::reset::{mutable_data_read_request::ReadIndexHint, read_request::ReadRequestStatus}; +use dep::types::{ + abis::{public_data_read::PublicDataRead, public_data_write::OverridablePublicDataWrite}, + data::OverridablePublicDataTreeLeaf, utils::arrays::find_index_hint +}; + +struct PublicDataReadRequestHints { + read_request_statuses: [ReadRequestStatus; NUM_READS], + pending_read_hints: [ReadIndexHint; NUM_READS], + leaf_data_read_hints: [ReadIndexHint; NUM_READS], +} + +unconstrained pub fn build_public_data_read_request_hints( + reads: [PublicDataRead; NUM_READS], + writes: [OverridablePublicDataWrite; NUM_WRITES], + leaf_data: [OverridablePublicDataTreeLeaf; NUM_LEAVES] +) -> PublicDataReadRequestHints { + let mut read_request_statuses = [ReadRequestStatus::empty(); NUM_READS]; + let mut pending_read_hints = [ReadIndexHint::nada(NUM_READS); NUM_READS]; + let mut leaf_data_read_hints = [ReadIndexHint::nada(NUM_READS); NUM_READS]; + let mut num_pending_reads = 0; + let mut num_leaf_data_reads = 0; + for i in 0..reads.len() { + let read = reads[i]; + if read.counter != 0 { + let write_index = find_index_hint( + writes, + |w: OverridablePublicDataWrite| (w.inner().leaf_slot == read.leaf_slot) & (read.counter > w.counter()) & ((read.counter < w.override_counter) | (w.override_counter == 0)) + ); + if write_index != writes.len() { + pending_read_hints[num_pending_reads] = ReadIndexHint { read_request_index: i, value_index: write_index }; + read_request_statuses[i] = ReadRequestStatus::pending(num_pending_reads); + num_pending_reads += 1; + } else { + let leaf_data_index = find_index_hint( + leaf_data, + |d: OverridablePublicDataTreeLeaf| d.leaf.slot == read.leaf_slot + ); + assert( + leaf_data_index != leaf_data.len(), "cannot find a public data leaf or a pending write for the read request" + ); + leaf_data_read_hints[num_leaf_data_reads] = ReadIndexHint { read_request_index: i, value_index: leaf_data_index }; + read_request_statuses[i] = ReadRequestStatus::settled(num_leaf_data_reads); + num_leaf_data_reads += 1; + } + } + } + + PublicDataReadRequestHints { read_request_statuses, pending_read_hints, leaf_data_read_hints } +} diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_data_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_data_read_request_reset.nr deleted file mode 100644 index 7c6b6634074..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_data_read_request_reset.nr +++ /dev/null @@ -1,9 +0,0 @@ -use crate::reset::{mutable_data_read_request::LeafDataReadHint, read_request::{PendingReadHint, ReadRequestStatus}}; -use dep::types::constants::MAX_PUBLIC_DATA_READS_PER_TX; - -// The MAX_PUBLIC_DATA_READS_PER_TX for pending_read_hints and leaf_data_read_hints can change if we create various circuits that deal with different number of reads. -struct PublicDataReadRequestHints { - read_request_statuses: [ReadRequestStatus; MAX_PUBLIC_DATA_READS_PER_TX], - pending_read_hints: [PendingReadHint; MAX_PUBLIC_DATA_READS_PER_TX], - leaf_data_read_hints: [LeafDataReadHint; MAX_PUBLIC_DATA_READS_PER_TX], -} diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr index 01fb966217d..a07fbef6114 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr @@ -7,25 +7,25 @@ use crate::{ }, nullifier_read_request_reset::NullifierReadRequestHints, nullifier_non_existent_read_request_reset::NullifierNonExistentReadRequestHints, - public_data_read_request_reset::PublicDataReadRequestHints + public_data_read_request_hints::PublicDataReadRequestHints }; use dep::types::{ abis::{ kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, nullifier::Nullifier, - public_data_update_request::PublicDataUpdateRequest, read_request::ScopedReadRequest, + public_data_write::OverridablePublicDataWrite, read_request::ScopedReadRequest, validation_requests::PublicValidationRequests }, - data::public_data_hint::PublicDataHint, constants::{ - L1_TO_L2_MSG_TREE_HEIGHT, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, L1_TO_L2_MSG_TREE_HEIGHT, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, NOTE_HASH_TREE_HEIGHT }, - hash::compute_siloed_nullifier, partial_state_reference::PartialStateReference, traits::is_empty, - utils::arrays::{array_merge, array_to_bounded_vec, assert_sorted_array} + data::OverridablePublicDataTreeLeaf, hash::compute_siloed_nullifier, + partial_state_reference::PartialStateReference, traits::is_empty, + utils::arrays::{array_to_bounded_vec, assert_combined_array, assert_sorted_array, combine_arrays} }; -struct PublicValidationRequestProcessor { +struct PublicValidationRequestProcessor { validation_requests: PublicValidationRequests, note_hash_read_request_hints: [TreeLeafReadRequestHint; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], note_hash_tree_root: Field, @@ -35,13 +35,12 @@ struct PublicValidationRequestProcessor { nullifier_tree_root: Field, l1_to_l2_msg_read_request_hints: [TreeLeafReadRequestHint; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX], l1_to_l2_msg_tree_root: Field, - pending_public_data_writes: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - public_data_read_request_hints: PublicDataReadRequestHints, - public_data_hints: [PublicDataHint; NUM_PUBLIC_DATA_HINTS], - public_data_tree_root: Field, + pending_public_data_writes: [OverridablePublicDataWrite; NUN_PUBLIC_DATA_WRITES], + public_data_leaves: [OverridablePublicDataTreeLeaf; NUM_PUBLIC_DATA_LEAVES], + public_data_read_request_hints: PublicDataReadRequestHints, } -impl PublicValidationRequestProcessor { +impl PublicValidationRequestProcessor { pub fn new( public_inputs: PublicKernelCircuitPublicInputs, start_state: PartialStateReference, @@ -49,33 +48,34 @@ impl PublicValidationRequestProcessor, nullifier_non_existent_read_request_hints: NullifierNonExistentReadRequestHints, l1_to_l2_msg_read_request_hints: [TreeLeafReadRequestHint; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX], - public_data_read_request_hints: PublicDataReadRequestHints, - public_data_hints: [PublicDataHint; NUM_PUBLIC_DATA_HINTS] + pending_public_data_writes: [OverridablePublicDataWrite; NUN_PUBLIC_DATA_WRITES], + public_data_leaves: [OverridablePublicDataTreeLeaf; NUM_PUBLIC_DATA_LEAVES], + public_data_read_request_hints: PublicDataReadRequestHints ) -> Self { - let end_non_revertible = public_inputs.end_non_revertible; - let end = public_inputs.end; - - let pending_nullifiers = array_merge(end_non_revertible.nullifiers, end.nullifiers); - - let pending_public_data_writes = array_merge( - end_non_revertible.public_data_update_requests, - end.public_data_update_requests + let non_revertible_nullifiers = public_inputs.end_non_revertible.nullifiers; + let revertible_nullifiers = public_inputs.end.nullifiers; + let pending_nullifiers = unsafe { + combine_arrays(non_revertible_nullifiers, revertible_nullifiers) + }; + assert_combined_array( + non_revertible_nullifiers, + revertible_nullifiers, + pending_nullifiers ); PublicValidationRequestProcessor { validation_requests: public_inputs.validation_requests, - pending_nullifiers, note_hash_read_request_hints, note_hash_tree_root: start_state.note_hash_tree.root, + pending_nullifiers, nullifier_read_request_hints, nullifier_non_existent_read_request_hints, nullifier_tree_root: start_state.nullifier_tree.root, l1_to_l2_msg_read_request_hints, l1_to_l2_msg_tree_root: public_inputs.constants.historical_header.state.l1_to_l2_message_tree.root, pending_public_data_writes, - public_data_read_request_hints, - public_data_hints, - public_data_tree_root: start_state.public_data_tree.root + public_data_leaves, + public_data_read_request_hints } } @@ -149,22 +149,15 @@ impl PublicValidationRequestProcessor Self { - LeafDataReadHint { read_request_index: read_request_len, data_hint_index: 0 } + ReadIndexHint { read_request_index: read_request_len, value_index: 0 } } } -fn validate_pending_read_requests( - read_requests: [PublicDataRead; READ_REQUEST_LEN], - data_writes: [PublicDataUpdateRequest; PENDING_VALUE_LEN], - hints: [PendingReadHint; NUM_PENDING_READS] -) { - for i in 0..NUM_PENDING_READS { - let read_request_index = hints[i].read_request_index; +fn validate_pending_read_requests( + read_requests: [R; READ_REQUEST_LEN], + pending_values: [V; PENDING_VALUE_LEN], + index_hints: [ReadIndexHint; NUM_HINTS] +) where R: Ordered, V: Readable + Ordered + Overridable { + for i in 0..index_hints.len() { + let index_hint = index_hints[i]; + let read_request_index = index_hint.read_request_index; if read_request_index != READ_REQUEST_LEN { let read_request = read_requests[read_request_index]; - let pending_value = data_writes[hints[i].pending_value_index]; + let pending_value = pending_values[index_hint.value_index]; + pending_value.assert_match_read_request(read_request); assert( - read_request.leaf_slot.eq(pending_value.leaf_slot), "Hinted slot of data write does not match read request" + read_request.counter() > pending_value.counter(), "Read request counter must be greater than the counter of the data write" ); assert( - read_request.value.eq(pending_value.new_value), "Hinted value of data write does not match read request" + (read_request.counter() < pending_value.override_counter()) + | (pending_value.override_counter() == 0), "Read request counter must be less than the counter of the next data write" ); - // TODO: Add counters and verify the following: - // assert( - // read_request.counter > pending_value.counter, "Read request counter must be greater than the counter of the data write" - // ); - // assert((read_request.counter < pending_value.next_counter) | (pending_value.next_counter == 0), "Read request counter must be less than the counter of the next data write"); } } } -fn validate_leaf_data_read_requests( - read_requests: [PublicDataRead; READ_REQUEST_LEN], - leaf_data_hints: [H; NUM_LEAF_DATA_HINTS], - hints: [LeafDataReadHint; NUM_LEAF_DATA_READS] -) where H: LeafDataHint { - for i in 0..NUM_LEAF_DATA_READS { - let read_request_index = hints[i].read_request_index; +fn validate_leaf_data_read_requests( + read_requests: [R; READ_REQUEST_LEN], + leaf_data: [L; LEAF_DATA_LEN], + index_hints: [ReadIndexHint; NUM_HINTS] +) where R: Ordered, L: Readable + Overridable { + for i in 0..index_hints.len() { + let index_hint = index_hints[i]; + let read_request_index = index_hint.read_request_index; if read_request_index != READ_REQUEST_LEN { let read_request = read_requests[read_request_index]; - let data_hint = leaf_data_hints[hints[i].data_hint_index]; + let data = leaf_data[index_hint.value_index]; + data.assert_match_read_request(read_request); assert( - read_request.leaf_slot == data_hint.leaf_slot(), "Hinted slot does not match read request" + (read_request.counter() < data.override_counter()) | (data.override_counter() == 0), "Hinted leaf is overridden before the read request" ); - assert(read_request.value == data_hint.value(), "Hinted value does not match read request"); - // TODO: Add counters and verify the following: - // assert((read_request.counter < data_hint.override_counter) | (data_hint.override_counter == 0), "Hinted leaf is overridden before the read request"); } } } -fn ensure_all_read_requests_are_verified( - read_requests: [PublicDataRead; READ_REQUEST_LEN], +fn ensure_all_read_requests_are_verified( + read_requests: [R; READ_REQUEST_LEN], read_request_statuses: [ReadRequestStatus; READ_REQUEST_LEN], - pending_read_hints: [PendingReadHint; NUM_PENDING_READS], - leaf_data_read_hints: [LeafDataReadHint; NUM_LEAF_DATA_READS] -) { + pending_read_hints: [ReadIndexHint; NUM_PENDING_READS], + leaf_data_read_hints: [ReadIndexHint; NUM_LEAF_DATA_READS] +) where R: Ordered { for i in 0..READ_REQUEST_LEN { let read_request = read_requests[i]; - if !is_empty(read_request) { + if read_request.counter() != 0 { let status = read_request_statuses[i]; if status.state == ReadRequestState.PENDING { assert( pending_read_hints[status.hint_index].read_request_index == i, "Hinted pending read request does not match status" ); - } else if status.state == ReadRequestState.SETTLED { + } else { assert( leaf_data_read_hints[status.hint_index].read_request_index == i, "Hinted settled read request does not match status" ); - } else { - assert(false, "Read request status must be PENDING or SETTLED"); } } } } pub fn reset_mutable_data_read_requests< + R, let READ_REQUEST_LEN: u32, + V, let PENDING_VALUE_LEN: u32, - H, + L, let NUM_LEAF_DATA_HINTS: u32, let NUM_PENDING_READS: u32, let NUM_LEAF_DATA_READS: u32 >( - read_requests: [PublicDataRead; READ_REQUEST_LEN], + read_requests: [R; READ_REQUEST_LEN], read_request_statuses: [ReadRequestStatus; READ_REQUEST_LEN], - data_writes: [PublicDataUpdateRequest; PENDING_VALUE_LEN], - leaf_data_hints: [H; NUM_LEAF_DATA_HINTS], - pending_read_hints: [PendingReadHint; NUM_PENDING_READS], - leaf_data_read_hints: [LeafDataReadHint; NUM_LEAF_DATA_READS] -) where H: LeafDataHint { - validate_pending_read_requests(read_requests, data_writes, pending_read_hints); + pending_values: [V; PENDING_VALUE_LEN], + leaf_data: [L; NUM_LEAF_DATA_HINTS], + pending_read_hints: [ReadIndexHint; NUM_PENDING_READS], + leaf_data_read_hints: [ReadIndexHint; NUM_LEAF_DATA_READS] +) where R: Ordered, V: Readable + Ordered + Overridable, L: Readable + Overridable { + validate_pending_read_requests(read_requests, pending_values, pending_read_hints); - validate_leaf_data_read_requests(read_requests, leaf_data_hints, leaf_data_read_hints); + validate_leaf_data_read_requests(read_requests, leaf_data, leaf_data_read_hints); ensure_all_read_requests_are_verified( read_requests, @@ -115,210 +109,359 @@ pub fn reset_mutable_data_read_requests< mod tests { use crate::reset::{ mutable_data_read_request::{ - ensure_all_read_requests_are_verified, reset_mutable_data_read_requests, LeafDataReadHint, + ensure_all_read_requests_are_verified, ReadIndexHint, reset_mutable_data_read_requests, validate_pending_read_requests, validate_leaf_data_read_requests }, - read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus} + read_request::{ReadRequestState, ReadRequestStatus} }; use dep::types::{ - abis::{public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest}, - data::leaf_data_hint::LeafDataHint + abis::{ + public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, + public_data_write::OverridablePublicDataWrite, side_effect::{Overridable, Readable} + }, + tests::utils::pad_end, traits::Empty }; - struct TestLeafDataHint { - leaf_slot: Field, + struct TestLeafData { + leaf_index: Field, value: Field, + override_counter: u32, } - impl LeafDataHint for TestLeafDataHint { - fn leaf_slot(self) -> Field { - self.leaf_slot + impl Empty for TestLeafData { + fn empty() -> Self { + TestLeafData { leaf_index: 0, value: 0, override_counter: 0 } } + } - fn value(self) -> Field { - self.value + impl Overridable for TestLeafData { + fn override_counter(self) -> u32 { + self.override_counter } + } - fn override_counter(_self: Self) -> u32 { - 0 + impl Readable for TestLeafData { + fn assert_match_read_request(self, read_request: PublicDataRead) { + assert_eq(self.leaf_index, read_request.leaf_slot, "leaf_index in TestLeafData does not match"); + assert_eq(self.value, read_request.value, "value in TestLeafData does not match"); } } - global data_writes = [ - PublicDataUpdateRequest { leaf_slot: 22, new_value: 200, counter: 0 }, - PublicDataUpdateRequest { leaf_slot: 11, new_value: 100, counter: 1 }, - PublicDataUpdateRequest { leaf_slot: 33, new_value: 300, counter: 2 }, - PublicDataUpdateRequest { leaf_slot: 44, new_value: 400, counter: 3 } - ]; - - global leaf_data_hints = [ - TestLeafDataHint { leaf_slot: 7, value: 70 }, - TestLeafDataHint { leaf_slot: 6, value: 60 }, - TestLeafDataHint { leaf_slot: 5, value: 50 }, - ]; - - fn create_pending_read_requests(data_write_indices: [u32; N]) -> ([PublicDataRead; N], [PendingReadHint; N]) { - let read_requests = data_write_indices.map( - |data_write_index: u32| PublicDataRead { leaf_slot: data_writes[data_write_index].leaf_slot, value: data_writes[data_write_index].new_value } - ); - let mut hints = BoundedVec::new(); - for i in 0..N { - hints.push(PendingReadHint { read_request_index: i, pending_value_index: data_write_indices[i] }); - } - (read_requests, hints.storage) + global READ_REQUEST_LEN = 10; + + struct TestBuilder { + read_requests: [PublicDataRead; READ_REQUEST_LEN], + read_request_statuses: [ReadRequestStatus; READ_REQUEST_LEN], + data_writes: [OverridablePublicDataWrite; 6], + leaf_data: [TestLeafData; 12], + pending_read_hints: [ReadIndexHint; 5], + leaf_data_read_hints: [ReadIndexHint; 4], + num_pending_reads: u32, + num_leaf_data_reads: u32, + counter: u32, } - fn create_leaf_data_read_requests(data_hint_indices: [u32; N]) -> ([PublicDataRead; N], [LeafDataReadHint; N]) { - let read_requests = data_hint_indices.map( - |data_hint_index: u32| PublicDataRead { leaf_slot: leaf_data_hints[data_hint_index].leaf_slot, value: leaf_data_hints[data_hint_index].value } - ); - let mut hints = BoundedVec::new(); - for i in 0..N { - hints.push(LeafDataReadHint { read_request_index: i, data_hint_index: data_hint_indices[i] }); + impl TestBuilder { + pub fn new() -> TestBuilder { + let read_requests = [PublicDataRead::empty(); READ_REQUEST_LEN]; + let read_request_statuses = [ReadRequestStatus::empty(); READ_REQUEST_LEN]; + + let leaf_data = pad_end( + [ + TestLeafData { leaf_index: 44, value: 0, override_counter: 40 }, + TestLeafData { leaf_index: 77, value: 700, override_counter: 0 }, + TestLeafData { leaf_index: 11, value: 0, override_counter: 20 }, + TestLeafData { leaf_index: 33, value: 300, override_counter: 30 }, + TestLeafData { leaf_index: 66, value: 600, override_counter: 0 }, + TestLeafData { leaf_index: 22, value: 200, override_counter: 10 }, + TestLeafData { leaf_index: 55, value: 500, override_counter: 0 } + ], + TestLeafData::empty() + ); + + let data_writes = pad_end( + [ + OverridablePublicDataWrite { write: PublicDataUpdateRequest { leaf_slot: 22, new_value: 201, counter: 10 }, override_counter: 40 }, + OverridablePublicDataWrite { write: PublicDataUpdateRequest { leaf_slot: 11, new_value: 100, counter: 20 }, override_counter: 0 }, + OverridablePublicDataWrite { write: PublicDataUpdateRequest { leaf_slot: 33, new_value: 301, counter: 30 }, override_counter: 0 }, + OverridablePublicDataWrite { write: PublicDataUpdateRequest { leaf_slot: 22, new_value: 202, counter: 40 }, override_counter: 0 } + ], + OverridablePublicDataWrite::empty() + ); + + let pending_read_hints = pad_end([], ReadIndexHint::nada(READ_REQUEST_LEN)); + + let leaf_data_read_hints = pad_end([], ReadIndexHint::nada(READ_REQUEST_LEN)); + + TestBuilder { + read_requests, + read_request_statuses, + leaf_data, + data_writes, + pending_read_hints, + leaf_data_read_hints, + num_pending_reads: 0, + num_leaf_data_reads: 0, + counter: 50 + } + } + + pub fn add_pending_read(&mut self, data_write_index: u32) { + let write = self.data_writes[data_write_index].write; + let read_request_index = self.num_pending_reads + self.num_leaf_data_reads; + self.read_requests[read_request_index] = PublicDataRead { + leaf_slot: write.leaf_slot, + value: write.new_value, + counter: self.counter + }; + self.pending_read_hints[self.num_pending_reads] = ReadIndexHint { read_request_index, value_index: data_write_index }; + self.read_request_statuses[read_request_index] = ReadRequestStatus::pending(self.num_pending_reads); + self.num_pending_reads += 1; + self.counter += 1; + } + + pub fn add_leaf_data_read(&mut self, data_hint_index: u32) { + let data_hint = self.leaf_data[data_hint_index]; + let read_request_index = self.num_pending_reads + self.num_leaf_data_reads; + self.read_requests[read_request_index] = PublicDataRead { + leaf_slot: data_hint.leaf_index, + value: data_hint.value, + counter: self.counter + }; + self.leaf_data_read_hints[self.num_leaf_data_reads] = ReadIndexHint { read_request_index, value_index: data_hint_index }; + self.read_request_statuses[read_request_index] = ReadRequestStatus::settled(self.num_leaf_data_reads); + self.num_leaf_data_reads += 1; + self.counter += 1; + } + + pub fn validate_pending_read_requests(self) { + validate_pending_read_requests(self.read_requests, self.data_writes, self.pending_read_hints); + } + + pub fn validate_leaf_data_read_requests(self) { + validate_leaf_data_read_requests(self.read_requests, self.leaf_data, self.leaf_data_read_hints) + } + + pub fn ensure_all_read_requests_are_verified(self) { + ensure_all_read_requests_are_verified( + self.read_requests, + self.read_request_statuses, + self.pending_read_hints, + self.leaf_data_read_hints + ) + } + + pub fn reset(self) { + reset_mutable_data_read_requests( + self.read_requests, + self.read_request_statuses, + self.data_writes, + self.leaf_data, + self.pending_read_hints, + self.leaf_data_read_hints + ); } - (read_requests, hints.storage) } #[test] fn reset_pending_reads_succeeds() { - let (read_requests, hints) = create_pending_read_requests([2, 0, 1, 3]); - validate_pending_read_requests(read_requests, data_writes, hints); + let mut builder = TestBuilder::new(); + + builder.add_pending_read(1); + builder.add_pending_read(2); + builder.add_pending_read(3); + + builder.validate_pending_read_requests(); } #[test] fn reset_pending_reads_repeated_values() { - let (read_requests, hints) = create_pending_read_requests([1, 0, 0, 1]); - validate_pending_read_requests(read_requests, data_writes, hints); + let mut builder = TestBuilder::new(); + + builder.add_pending_read(2); + builder.add_pending_read(2); + builder.add_pending_read(2); + + builder.validate_pending_read_requests(); + } + + #[test(should_fail_with="Read request counter must be less than the counter of the next data write")] + fn reset_pending_reads_overriden_value_fails() { + let mut builder = TestBuilder::new(); + + // 0th write is overriden by the 3rd write. + builder.add_pending_read(0); + + builder.validate_pending_read_requests(); } #[test] - fn reset_pending_reads_skips_nada() { - let read_requests = [PublicDataRead { leaf_slot: 88, value: 9999 }]; - let hints = [PendingReadHint::nada(1)]; - validate_pending_read_requests(read_requests, data_writes, hints); + fn reset_pending_reads_overriden_value_before_next_succeeds() { + let mut builder = TestBuilder::new(); + + // 0th write is overriden by the 3rd write. + builder.add_pending_read(0); + + // Tweak the counter of the read request to be before the next value. + builder.read_requests[0].counter = builder.data_writes[3].write.counter - 1; + + builder.validate_pending_read_requests(); } - #[test(should_fail_with="Hinted slot of data write does not match read request")] + #[test(should_fail_with="leaf_slot in OverridablePublicDataWrite does not match read request")] fn reset_pending_reads_wrong_slot_fails() { - let mut (read_requests, hints) = create_pending_read_requests([1]); - hints[0].pending_value_index = 0; - validate_pending_read_requests(read_requests, data_writes, hints); + let mut builder = TestBuilder::new(); + + builder.add_pending_read(2); + builder.read_requests[0].leaf_slot += 1; + + builder.validate_pending_read_requests(); } - #[test(should_fail_with="Hinted value of data write does not match read request")] + #[test(should_fail_with="value in OverridablePublicDataWrite does not match read request")] fn reset_pending_reads_wrong_value_fails() { - let mut (read_requests, hints) = create_pending_read_requests([1]); - read_requests[0].value += 1; - validate_pending_read_requests(read_requests, data_writes, hints); + let mut builder = TestBuilder::new(); + + builder.add_pending_read(2); + builder.read_requests[0].value += 1; + + builder.validate_pending_read_requests(); + } + + #[test(should_fail_with="Read request counter must be greater than the counter of the data write")] + fn reset_pending_reads_value_write_after_fails() { + let mut builder = TestBuilder::new(); + + builder.add_pending_read(2); + builder.read_requests[0].counter = builder.data_writes[2].write.counter - 1; + + builder.validate_pending_read_requests(); } #[test] fn reset_leaf_data_reads_succeeds() { - let (read_requests, hints) = create_leaf_data_read_requests([2, 1, 0]); - validate_leaf_data_read_requests(read_requests, leaf_data_hints, hints); + let mut builder = TestBuilder::new(); + + builder.add_leaf_data_read(1); + builder.add_leaf_data_read(4); + builder.add_leaf_data_read(6); + + builder.validate_leaf_data_read_requests(); } #[test] fn reset_leaf_data_reads_repeated_values() { - let (read_requests, hints) = create_leaf_data_read_requests([1, 0, 1, 0]); - validate_leaf_data_read_requests(read_requests, leaf_data_hints, hints); + let mut builder = TestBuilder::new(); + + builder.add_leaf_data_read(4); + builder.add_leaf_data_read(4); + builder.add_leaf_data_read(4); + + builder.validate_leaf_data_read_requests(); + } + + #[test(should_fail_with="Hinted leaf is overridden before the read request")] + fn reset_leaf_data_reads_overriden_value_fails() { + let mut builder = TestBuilder::new(); + + // 2nd leaf is overriden by a pending write. + builder.add_leaf_data_read(2); + + builder.validate_leaf_data_read_requests(); } #[test] - fn reset_leaf_data_reads_skips_nada() { - let read_requests = [PublicDataRead { leaf_slot: 88, value: 9999 }]; - let hints = [LeafDataReadHint::nada(1)]; - validate_leaf_data_read_requests(read_requests, leaf_data_hints, hints); + fn reset_leaf_data_reads_overriden_value_before_next_succeeds() { + let mut builder = TestBuilder::new(); + + // 2nd leaf is overriden by a pending write. + builder.add_leaf_data_read(2); + + // Tweak the counter of the read request to be before the pending write. + builder.read_requests[0].counter = builder.leaf_data[2].override_counter - 1; + + builder.validate_leaf_data_read_requests(); } - #[test(should_fail_with=""Hinted slot does not match read request")] + #[test(should_fail_with=""leaf_index in TestLeafData does not match")] fn reset_leaf_reads_wrong_slot_fails() { - let mut (read_requests, hints) = create_leaf_data_read_requests([1]); - hints[0].data_hint_index = 0; - validate_leaf_data_read_requests(read_requests, leaf_data_hints, hints); + let mut builder = TestBuilder::new(); + + builder.add_leaf_data_read(4); + builder.read_requests[0].leaf_slot += 1; + + builder.validate_leaf_data_read_requests(); } - #[test(should_fail_with=""Hinted value does not match read request")] + #[test(should_fail_with=""value in TestLeafData does not match")] fn reset_leaf_reads_wrong_value_fails() { - let mut (read_requests, hints) = create_leaf_data_read_requests([1]); - read_requests[0].value += 1; - validate_leaf_data_read_requests(read_requests, leaf_data_hints, hints); + let mut builder = TestBuilder::new(); + + builder.add_leaf_data_read(4); + builder.read_requests[0].value += 1; + + builder.validate_leaf_data_read_requests(); } #[test] fn ensure_all_read_requests_are_verified_succeeds() { - let mut (pending_read_requests, pending_read_hints) = create_pending_read_requests([1]); - let mut (leaf_read_requests, leaf_data_read_hints) = create_leaf_data_read_requests([0, 1]); - let read_requests = [leaf_read_requests[0], pending_read_requests[0], leaf_read_requests[1]]; - pending_read_hints[0].read_request_index = 1; - leaf_data_read_hints[1].read_request_index = 2; - - let statuses = [ - ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 0 }, - ReadRequestStatus { state: ReadRequestState.PENDING, hint_index: 0 }, - ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 1 } - ]; - - ensure_all_read_requests_are_verified( - read_requests, - statuses, - pending_read_hints, - leaf_data_read_hints - ); + let mut builder = TestBuilder::new(); + + builder.add_leaf_data_read(4); + builder.add_pending_read(2); + builder.add_pending_read(1); + builder.add_leaf_data_read(1); + + builder.ensure_all_read_requests_are_verified(); } #[test(should_fail_with="Hinted pending read request does not match status")] fn ensure_all_read_requests_are_verified_wrong_pending_hint_index_fails() { - let (read_requests, hints) = create_pending_read_requests([0, 1]); - let statuses = [ - ReadRequestStatus { state: ReadRequestState.PENDING, hint_index: 0 }, - ReadRequestStatus { state: ReadRequestState.PENDING, hint_index: 0 } - ]; - ensure_all_read_requests_are_verified(read_requests, statuses, hints, []); + let mut builder = TestBuilder::new(); + + builder.add_pending_read(2); + builder.read_request_statuses[0].hint_index += 1; + + builder.ensure_all_read_requests_are_verified(); } #[test(should_fail_with="Hinted settled read request does not match status")] fn ensure_all_read_requests_are_verified_wrong_leaf_hint_index_fails() { - let (read_requests, hints) = create_leaf_data_read_requests([0, 1]); - let statuses = [ - ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 0 }, - ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 0 } - ]; - ensure_all_read_requests_are_verified(read_requests, statuses, [], hints); + let mut builder = TestBuilder::new(); + + builder.add_leaf_data_read(4); + builder.read_request_statuses[0].hint_index += 1; + + builder.ensure_all_read_requests_are_verified(); } - #[test(should_fail_with="Read request status must be PENDING or SETTLED")] + #[test(should_fail_with="Hinted settled read request does not match status")] fn ensure_all_read_requests_are_verified_wrong_status_fails() { - let (read_requests, hints) = create_leaf_data_read_requests([0]); - let statuses = [ReadRequestStatus { state: ReadRequestState.NADA, hint_index: 0 }]; - ensure_all_read_requests_are_verified(read_requests, statuses, [], hints); + let mut builder = TestBuilder::new(); + + builder.add_pending_read(2); + builder.read_request_statuses[0].state = ReadRequestState.NADA; + + builder.ensure_all_read_requests_are_verified(); } #[test] fn reset_mutable_data_read_requests_succeeds() { - let mut (pending_read_requests, pending_read_hints) = create_pending_read_requests([3, 1]); - let mut (leaf_read_requests, leaf_data_read_hints) = create_leaf_data_read_requests([0, 1]); - let read_requests = [ - leaf_read_requests[0], pending_read_requests[0], pending_read_requests[1], leaf_read_requests[1] - ]; - pending_read_hints[0].read_request_index = 1; - pending_read_hints[1].read_request_index = 2; - leaf_data_read_hints[1].read_request_index = 3; - - let statuses = [ - ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 0 }, - ReadRequestStatus { state: ReadRequestState.PENDING, hint_index: 0 }, - ReadRequestStatus { state: ReadRequestState.PENDING, hint_index: 1 }, - ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 1 } - ]; - - reset_mutable_data_read_requests( - read_requests, - statuses, - data_writes, - leaf_data_hints, - pending_read_hints, - leaf_data_read_hints - ); + let mut builder = TestBuilder::new(); + + builder.add_pending_read(1); + builder.add_leaf_data_read(4); + builder.add_pending_read(2); + builder.add_leaf_data_read(6); + builder.add_leaf_data_read(6); + builder.add_pending_read(1); + + builder.reset(); + } + + #[test] + fn reset_mutable_data_read_requests_no_requests_succeeds() { + let builder = TestBuilder::new(); + builder.reset(); } } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr index c7f35b84da8..9735a8f517c 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr @@ -1,7 +1,7 @@ use dep::types::{ abis::{side_effect::OrderedValue, read_request::ScopedReadRequest}, merkle_tree::{assert_check_non_membership, IndexedTreeLeafPreimage, MembershipWitness}, - traits::{Empty, is_empty} + traits::is_empty }; trait NonMembershipHint where LEAF_PREIMAGE: IndexedTreeLeafPreimage { @@ -89,8 +89,7 @@ mod tests { use crate::reset::non_existent_read_request::{NonMembershipHint, reset_non_existent_read_requests}; use dep::types::{ - address::AztecAddress, - abis::{read_request::{ReadRequest, ScopedReadRequest}, side_effect::OrderedValue}, + address::AztecAddress, abis::{read_request::ReadRequest, side_effect::OrderedValue}, merkle_tree::{leaf_preimage::IndexedTreeLeafPreimage, membership::MembershipWitness}, tests::merkle_tree_utils::NonEmptyMerkleTree }; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/read_request.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/read_request.nr index 6a63c52afbe..25e615381f9 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/read_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/read_request.nr @@ -27,6 +27,16 @@ impl Empty for ReadRequestStatus { } } +impl ReadRequestStatus { + pub fn pending(hint_index: u32) -> Self { + ReadRequestStatus { state: ReadRequestState.PENDING, hint_index } + } + + pub fn settled(hint_index: u32) -> Self { + ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index } + } +} + trait ReadValueHint { fn read_request_index(self) -> u32; } @@ -62,7 +72,7 @@ fn validate_pending_read_requests { for i in 0..NUM_PENDING_READS { let hint = hints[i]; let read_request_index = hint.read_request_index; @@ -82,7 +92,7 @@ fn validate_settled_read_requests + ReadValueHint, - LEAF_PREIMAGE: LeafPreimage + Readable { + LEAF_PREIMAGE: LeafPreimage + Readable { for i in 0..NUM_SETTLED_READS { let hint = hints[i]; let read_request_index = hint.read_request_index(); @@ -144,9 +154,9 @@ pub fn verify_reset_read_requests< tree_root: Field, propagated_read_requests: [ScopedReadRequest; READ_REQUEST_LEN] ) where - P: Readable, + P: Readable, H: SettledReadHint + ReadValueHint, - LEAF_PREIMAGE: LeafPreimage + Readable { + LEAF_PREIMAGE: LeafPreimage + Readable { validate_pending_read_requests(read_requests, pending_values, pending_read_hints); validate_settled_read_requests(read_requests, settled_read_hints, tree_root); @@ -197,7 +207,7 @@ mod tests { counter: u32, } - impl Readable for TestValue { + impl Readable for TestValue { fn assert_match_read_request(self, read_request: ScopedReadRequest) { let siloed_value = silo_test_value(read_request.value()); assert_eq(self.value, siloed_value, "Hinted test value does not match"); @@ -226,7 +236,7 @@ mod tests { } } - impl Readable for TestLeafPreimage { + impl Readable for TestLeafPreimage { fn assert_match_read_request(self, read_request: ScopedReadRequest) { let siloed_value = silo_test_value(read_request.value()); assert_eq(siloed_value, self.value, "Provided leaf preimage is not for target value"); @@ -348,7 +358,7 @@ mod tests { TestSettledReadHint::nada(self.read_requests.len()) } - pub fn get_unverified_read_requests(self) -> [ScopedReadRequest; READ_REQUEST_LEN] { + unconstrained pub fn get_unverified_read_requests(self) -> [ScopedReadRequest; READ_REQUEST_LEN] { get_unverified_read_requests(self.read_requests, self.read_request_statuses) } @@ -375,6 +385,9 @@ mod tests { pub fn verify_with_settled_hints(self, settled_hints: [TestSettledReadHint; 2]) { let tree = self.build_tree(); + let unverified = unsafe { + self.get_unverified_read_requests() + }; verify_reset_read_requests( self.read_requests, self.pending_values, @@ -382,12 +395,15 @@ mod tests { self.pending_read_hints, settled_hints, tree.get_root(), - self.get_unverified_read_requests() + unverified ); } pub fn verify(self) { let (settled_hints, tree_root) = self.get_settled_read_hints(); + let unverified = unsafe { + self.get_unverified_read_requests() + }; verify_reset_read_requests( self.read_requests, self.pending_values, @@ -395,7 +411,7 @@ mod tests { self.pending_read_hints, settled_hints, tree_root, - self.get_unverified_read_requests() + unverified ); } } @@ -497,7 +513,9 @@ mod tests { fn verify_read_requests_clears_all_succeeds() { let builder = TestBuilder::new(); - let unverified_read_requests = builder.get_unverified_read_requests(); + let unverified_read_requests = unsafe { + builder.get_unverified_read_requests() + }; assert(is_empty_array(unverified_read_requests)); builder.verify(); @@ -515,7 +533,9 @@ mod tests { settled_hints[0] = builder.get_nada_settled_read_hint(); let read_requests = builder.read_requests; - let unverified_read_requests = builder.get_unverified_read_requests(); + let unverified_read_requests = unsafe { + builder.get_unverified_read_requests() + }; assert_array_eq( unverified_read_requests, [read_requests[0], read_requests[2]] diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr index 62e81931aaa..d0c1f2c7f37 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr @@ -162,8 +162,12 @@ pub fn verify_squashed_transient_data< transient_or_propagated_note_hash_indexes_for_logs: [u32; NUM_LOGS], split_counter: u32 ) { - let squashed_note_hash_hints = get_squashed_note_hash_hints(transient_data_index_hints); - let squashed_nullifier_hints = get_squashed_nullifier_hints(transient_data_index_hints); + let squashed_note_hash_hints = unsafe { + get_squashed_note_hash_hints(transient_data_index_hints) + }; + let squashed_nullifier_hints = unsafe { + get_squashed_nullifier_hints(transient_data_index_hints) + }; verify_squashed_transient_data_with_hint_indexes( note_hashes, nullifiers, @@ -353,8 +357,12 @@ mod tests { } pub fn get_hint_indexes(self) -> ([bool; NUM_NOTE_HASHES], [bool; NUM_NULLIFIERS]) { - let squashed_note_hash_hints = get_squashed_note_hash_hints(self.transient_data_index_hints); - let squashed_nullifier_hints = get_squashed_nullifier_hints(self.transient_data_index_hints); + let squashed_note_hash_hints = unsafe { + get_squashed_note_hash_hints(self.transient_data_index_hints) + }; + let squashed_nullifier_hints = unsafe { + get_squashed_nullifier_hints(self.transient_data_index_hints) + }; (squashed_note_hash_hints, squashed_nullifier_hints) } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/mod.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/mod.nr index dd0fa37a7cd..3d21477493f 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/mod.nr @@ -1,7 +1,6 @@ mod note_hash_read_request_hints_builder; mod nullifier_non_existent_read_request_hints_builder; mod nullifier_read_request_hints_builder; -mod public_data_read_request_hints_builder; -use note_hash_read_request_hints_builder::NoteHashReadRequestHintsBuilder; -use nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder; +pub use note_hash_read_request_hints_builder::NoteHashReadRequestHintsBuilder; +pub use nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr index d50f63628c1..5e68a57b14b 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr @@ -22,7 +22,7 @@ impl NoteHashReadRequest } } - pub fn to_hints(self) -> NoteHashReadRequestHints { + unconstrained pub fn to_hints(self) -> NoteHashReadRequestHints { NoteHashReadRequestHints { read_request_statuses: self.read_request_statuses, pending_read_hints: self.pending_read_hints.storage, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr index ea0d8affd55..27f2fc56b1e 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr @@ -6,7 +6,7 @@ use dep::types::{ NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT }, merkle_tree::MembershipWitness, tests::{merkle_tree_utils::NonEmptyMerkleTree}, - utils::{arrays::{find_index_hint, get_sorted_hints}, field::full_field_greater_than} + utils::{arrays::{find_index_hint, get_sorted_result}} }; struct NullifierNonExistentReadRequestHintsBuilder { @@ -49,8 +49,8 @@ impl NullifierNonExistentReadRequestHintsBuilder { self.non_membership_hints.push(hint); } - pub fn to_hints(self) -> NullifierNonExistentReadRequestHints { - let sorted_result = get_sorted_hints( + unconstrained pub fn to_hints(self) -> NullifierNonExistentReadRequestHints { + let sorted_result = get_sorted_result( self.pending_nullifiers, |a: Nullifier, b: Nullifier| (b.value == 0) | ((a.value != 0) & a.value.lt(b.value)) ); diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr index 7a019b9fae2..a6691f45eaa 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr @@ -22,7 +22,7 @@ impl NullifierReadReques } } - pub fn to_hints(self) -> NullifierReadRequestHints { + unconstrained pub fn to_hints(self) -> NullifierReadRequestHints { NullifierReadRequestHints { read_request_statuses: self.read_request_statuses, pending_read_hints: self.pending_read_hints.storage, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/public_data_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/public_data_read_request_hints_builder.nr deleted file mode 100644 index d2de7f04cd5..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/public_data_read_request_hints_builder.nr +++ /dev/null @@ -1,29 +0,0 @@ -use crate::{ - public_data_read_request_reset::PublicDataReadRequestHints, - reset::{mutable_data_read_request::LeafDataReadHint, read_request::{PendingReadHint, ReadRequestStatus}} -}; -use dep::types::constants::MAX_PUBLIC_DATA_READS_PER_TX; - -struct PublicDataReadRequestHintsBuilder { - read_request_statuses: [ReadRequestStatus; MAX_PUBLIC_DATA_READS_PER_TX], - pending_read_hints: BoundedVec, - leaf_data_read_hints: BoundedVec, -} - -impl PublicDataReadRequestHintsBuilder { - pub fn new(read_request_len: u32) -> Self { - PublicDataReadRequestHintsBuilder { - read_request_statuses: [ReadRequestStatus::empty(); MAX_PUBLIC_DATA_READS_PER_TX], - pending_read_hints: BoundedVec { storage: [PendingReadHint::nada(read_request_len); MAX_PUBLIC_DATA_READS_PER_TX], len: 0 }, - leaf_data_read_hints: BoundedVec { storage: [LeafDataReadHint::nada(read_request_len); MAX_PUBLIC_DATA_READS_PER_TX], len: 0 } - } - } - - pub fn to_hints(self) -> PublicDataReadRequestHints { - PublicDataReadRequestHints { - read_request_statuses: self.read_request_statuses, - pending_read_hints: self.pending_read_hints.storage, - leaf_data_read_hints: self.leaf_data_read_hints.storage - } - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr index cbe1a5cb28b..34b40ff3263 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr @@ -1,5 +1,4 @@ use dep::types::{ - abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH, partial_state_reference::PartialStateReference, traits::{Empty, Serialize, Deserialize}, utils::reader::Reader }; @@ -24,7 +23,7 @@ struct BaseOrMergeRollupPublicInputs { // We hash public inputs to make them constant-sized (to then be unpacked on-chain) txs_effects_hash : Field, - out_hash : Field, + out_hash : Field, accumulated_fees: Field } @@ -38,7 +37,7 @@ impl Empty for BaseOrMergeRollupPublicInputs { start: PartialStateReference::empty(), end: PartialStateReference::empty(), txs_effects_hash : 0, - out_hash : 0, + out_hash : 0, accumulated_fees: 0 } } @@ -82,7 +81,7 @@ impl Deserialize for BaseOrMergeRollupPublic let item = Self { rollup_type: reader.read() as u32, num_txs: reader.read() as u32, - constants: reader.read_struct(ConstantRollupData::deserialize), + constants: reader.read_struct(ConstantRollupData::deserialize), start: reader.read_struct(PartialStateReference::deserialize), end: reader.read_struct(PartialStateReference::deserialize), txs_effects_hash: reader.read(), diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr index 5ccb79061fd..56009c9e2ff 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr @@ -1,10 +1,8 @@ use dep::types::{ abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot, global_variables::GlobalVariables}, - constants::BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH, - partial_state_reference::PartialStateReference, traits::{Empty, Serialize, Deserialize}, + constants::BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH, traits::{Empty, Serialize, Deserialize}, utils::reader::Reader, address::EthAddress }; -use crate::abis::constant_rollup_data::ConstantRollupData; struct FeeRecipient { recipient: EthAddress, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr index da846f9d34e..593c44d2bab 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr @@ -39,7 +39,9 @@ impl Empty for PreviousRollupBlockData { impl PreviousRollupBlockData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { let leaf_index = self.vk_witness.leaf_index as u32; - let index_hint = find_index_hint(allowed_indices, |index: u32| index == leaf_index); + let index_hint = unsafe { + find_index_hint(allowed_indices, |index: u32| index == leaf_index) + }; assert_eq(allowed_indices[index_hint], leaf_index, "Invalid vk index"); assert_check_membership( diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr index b0e71945b43..aa7e1de178b 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr @@ -39,7 +39,9 @@ impl Empty for PreviousRollupData { impl PreviousRollupData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { let leaf_index = self.vk_witness.leaf_index as u32; - let index_hint = find_index_hint(allowed_indices, |index: u32| index == leaf_index); + let index_hint = unsafe { + find_index_hint(allowed_indices, |index: u32| index == leaf_index) + }; assert_eq(allowed_indices[index_hint], leaf_index, "Invalid vk index"); assert_check_membership( diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr index a9b8418ec09..a42e25a10b5 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -7,7 +7,7 @@ use crate::{ components::{compute_tx_effects_hash, compute_kernel_out_hash} }; use dep::types::{ - hash::{sha256_to_field, silo_l2_to_l1_message}, + hash::silo_l2_to_l1_message, data::{ public_data_hint::PublicDataHint, hash::{compute_public_data_tree_index, compute_public_data_tree_value} @@ -15,27 +15,23 @@ use dep::types::{ storage::map::derive_storage_slot_in_map, address::AztecAddress, abis::{ append_only_tree_snapshot::AppendOnlyTreeSnapshot, nullifier_leaf_preimage::NullifierLeafPreimage, - public_data_update_request::PublicDataUpdateRequest, public_data_read::PublicDataRead, - kernel_data::KernelData + public_data_update_request::PublicDataUpdateRequest, kernel_data::KernelData }, messaging::l2_to_l1_message::ScopedL2ToL1Message, constants::{ - NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT, NOTE_HASH_SUBTREE_HEIGHT, MAX_NOTE_HASHES_PER_TX, - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_L2_TO_L1_MSGS_PER_TX, NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_TREE_HEIGHT, - PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_SUBTREE_HEIGHT, - PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ARCHIVE_HEIGHT, FEE_JUICE_ADDRESS, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_KERNEL_TAIL_INDEX, PRIVATE_KERNEL_EMPTY_INDEX, - PRIVATE_KERNEL_TAIL_INDEX + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_TREE_HEIGHT, + PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_SUBTREE_HEIGHT, ARCHIVE_HEIGHT, + FEE_JUICE_ADDRESS, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_KERNEL_TAIL_INDEX, + PRIVATE_KERNEL_EMPTY_INDEX, PRIVATE_KERNEL_TAIL_INDEX }, merkle_tree::{ append_only_tree, assert_check_membership, calculate_empty_tree_root, calculate_subtree_root, indexed_tree, MembershipWitness }, - partial_state_reference::PartialStateReference, public_data_tree_leaf::PublicDataTreeLeaf, - public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, traits::is_empty, - utils::{field::{full_field_less_than, full_field_greater_than}, uint256::U256} + partial_state_reference::PartialStateReference, + data::{PublicDataTreeLeaf, PublicDataTreeLeafPreimage}, traits::is_empty, + utils::{field::{full_field_less_than, full_field_greater_than}} }; global ALLOWED_PREVIOUS_CIRCUITS = [ @@ -280,7 +276,9 @@ impl BaseRollupInputs { if read_hint.leaf_slot == 0 { // Is there a balance update already in this tx? If so, update it and return its index. - let existing_update_index = self.find_fee_payer_fee_juice_update_index(leaf_slot); + let existing_update_index = unsafe { + self.find_fee_payer_fee_juice_update_index(leaf_slot) + }; let existing_update = self.kernel_data.public_inputs.end.public_data_update_requests[existing_update_index]; assert( existing_update.leaf_slot == leaf_slot, "Wrong leaf slot for Fee Juice balance update request" @@ -460,41 +458,35 @@ mod tests { }, base::{ state_diff_hints::StateDiffHints, - base_rollup_inputs::{BaseRollupInputs, compute_fee_payer_fee_juice_balance_leaf_slot, ALLOWED_PREVIOUS_CIRCUITS} + base_rollup_inputs::{BaseRollupInputs, compute_fee_payer_fee_juice_balance_leaf_slot} }, - components::{TX_EFFECTS_HASH_INPUT_FIELDS, compute_kernel_out_hash} + components::TX_EFFECTS_HASH_INPUT_FIELDS }; use dep::types::{ abis::{ append_only_tree_snapshot::AppendOnlyTreeSnapshot, - nullifier_leaf_preimage::NullifierLeafPreimage, public_data_read::PublicDataRead, - public_data_update_request::PublicDataUpdateRequest, kernel_data::KernelData, - accumulated_data::CombinedAccumulatedData, gas::Gas + nullifier_leaf_preimage::NullifierLeafPreimage, + public_data_update_request::PublicDataUpdateRequest, kernel_data::KernelData }, messaging::l2_to_l1_message::ScopedL2ToL1Message, merkle_tree::MembershipWitness, hash::silo_l2_to_l1_message, data::public_data_hint::PublicDataHint, address::{AztecAddress, EthAddress}, constants::{ - ARCHIVE_HEIGHT, MAX_PUBLIC_DATA_READS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, - NOTE_HASH_TREE_HEIGHT, NOTE_HASH_SUBTREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, - NULLIFIER_TREE_HEIGHT, NULLIFIER_SUBTREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, - PUBLIC_DATA_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, MAX_L2_TO_L1_MSGS_PER_TX, + ARCHIVE_HEIGHT, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NOTE_HASH_TREE_HEIGHT, + NOTE_HASH_SUBTREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, + NULLIFIER_SUBTREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, PUBLIC_DATA_SUBTREE_HEIGHT, + PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, MAX_L2_TO_L1_MSGS_PER_TX, PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - BASE_ROLLUP_INDEX, PRIVATE_KERNEL_EMPTY_INDEX, PRIVATE_KERNEL_TAIL_INDEX, - PUBLIC_KERNEL_TAIL_INDEX + PRIVATE_KERNEL_EMPTY_INDEX, PRIVATE_KERNEL_TAIL_INDEX, PUBLIC_KERNEL_TAIL_INDEX }, - contract_class_id::ContractClassId, partial_state_reference::PartialStateReference, - public_data_tree_leaf::PublicDataTreeLeaf, - public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, + partial_state_reference::PartialStateReference, + data::{PublicDataTreeLeaf, PublicDataTreeLeafPreimage}, tests::{ fixtures, fixture_builder::FixtureBuilder, merkle_tree_utils::{NonEmptyMerkleTree, compute_zero_hashes} }, - utils::{ - arrays::get_sorted_tuple::get_sorted_tuple, - field::{full_field_less_than, field_from_bytes_32_trunc, field_from_bytes}, uint256::U256 - }, + utils::{arrays::get_sorted_tuple::get_sorted_tuple, field::{full_field_less_than, field_from_bytes_32_trunc}}, traits::Empty }; @@ -540,10 +532,12 @@ mod tests { final_public_data_writes.extend_from_array(protocol_public_data_writes.storage); } - let mut sorted_write_tuples = get_sorted_tuple( - final_public_data_writes.storage, - |(_, leaf_a): (u32, PublicDataTreeLeaf), (_, leaf_b): (u32, PublicDataTreeLeaf)| full_field_less_than(leaf_b.slot, leaf_a.slot) - ); + let mut sorted_write_tuples = unsafe { + get_sorted_tuple( + final_public_data_writes.storage, + |(_, leaf_a): (u32, PublicDataTreeLeaf), (_, leaf_b): (u32, PublicDataTreeLeaf)| full_field_less_than(leaf_b.slot, leaf_a.slot) + ) + }; for i in 0..MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { if i < final_public_data_writes.len() { @@ -673,10 +667,12 @@ mod tests { let mut nullifier_predecessor_preimages = [NullifierLeafPreimage::empty(); MAX_NULLIFIERS_PER_TX]; let mut low_nullifier_membership_witness = [MembershipWitness::empty(); MAX_NULLIFIERS_PER_TX]; - let sorted_new_nullifier_tuples = get_sorted_tuple( - self.nullifiers.storage.map(|insertion: NullifierInsertion| insertion.value), - |a, b| full_field_less_than(b, a) - ); + let sorted_new_nullifier_tuples = unsafe { + get_sorted_tuple( + self.nullifiers.storage.map(|insertion: NullifierInsertion| insertion.value), + |a, b| full_field_less_than(b, a) + ) + }; let mut sorted_nullifiers = [0; MAX_NULLIFIERS_PER_TX]; let mut sorted_nullifiers_indexes = [0; MAX_NULLIFIERS_PER_TX]; @@ -904,10 +900,6 @@ mod tests { #[test] unconstrained fn new_nullifier_tree_empty() { - /** - * DESCRIPTION - */ - // This test checks for insertions of all 0 values // In this special case we will not need to provide sibling paths to check insertion of the nullifier values // This is because 0 values are not actually inserted into the tree, rather the inserted subtree is left diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/mod.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/mod.nr index 26987302495..d7de5b52f98 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/mod.nr @@ -1,5 +1,5 @@ mod base_rollup_inputs; mod state_diff_hints; -use base_rollup_inputs::BaseRollupInputs; -use crate::abis::base_or_merge_rollup_public_inputs::BaseOrMergeRollupPublicInputs; +pub use base_rollup_inputs::BaseRollupInputs; +pub use crate::abis::base_or_merge_rollup_public_inputs::BaseOrMergeRollupPublicInputs; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr index 45dc272dd8f..dce74c2022f 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr @@ -69,11 +69,8 @@ impl BlockMergeRollupInputs { } mod tests { - use crate::{ - block_merge::block_merge_rollup_inputs::BlockMergeRollupInputs, - tests::block_merge_rollup_inputs::default_block_merge_rollup_inputs - }; - use dep::types::{hash::accumulate_sha256, address::EthAddress}; + use crate::{tests::block_merge_rollup_inputs::default_block_merge_rollup_inputs}; + use dep::types::{hash::accumulate_sha256}; use dep::types::constants::{BLOCK_ROOT_ROLLUP_INDEX, BLOCK_MERGE_ROLLUP_INDEX}; #[test(should_fail_with="input blocks have different chain id")] diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/mod.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/mod.nr index a677abf9300..e6e595f1091 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/mod.nr @@ -1,3 +1,4 @@ mod block_merge_rollup_inputs; -use block_merge_rollup_inputs::BlockMergeRollupInputs; -use crate::abis::block_root_or_block_merge_public_inputs::BlockRootOrBlockMergePublicInputs; + +pub use block_merge_rollup_inputs::BlockMergeRollupInputs; +pub use crate::abis::block_root_or_block_merge_public_inputs::BlockRootOrBlockMergePublicInputs; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr index f9cbed86313..aaea86a0bb7 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr @@ -1,21 +1,20 @@ use crate::{ abis::{ - previous_rollup_data::PreviousRollupData, constant_rollup_data::ConstantRollupData, + previous_rollup_data::PreviousRollupData, block_root_or_block_merge_public_inputs::{BlockRootOrBlockMergePublicInputs, FeeRecipient} }, components }; -use parity_lib::{root::root_rollup_parity_input::RootRollupParityInput, ParityPublicInputs}; +use parity_lib::{root::root_rollup_parity_input::RootRollupParityInput}; use types::{ - abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot, nullifier_leaf_preimage::NullifierLeafPreimage}, - address::EthAddress, + abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot}, constants::{ NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, L1_TO_L2_MSG_SUBTREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, ARCHIVE_HEIGHT, BASE_ROLLUP_INDEX, MERGE_ROLLUP_INDEX }, header::Header, content_commitment::ContentCommitment, - merkle_tree::{append_only_tree, calculate_subtree_root, calculate_empty_tree_root}, - state_reference::StateReference, traits::Empty + merkle_tree::{append_only_tree, calculate_empty_tree_root}, state_reference::StateReference, + traits::Empty }; global ALLOWED_PREVIOUS_CIRCUITS = [ diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/mod.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/mod.nr index 350e051b2fa..71538bcb1f7 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/mod.nr @@ -1,8 +1,8 @@ mod block_root_rollup_inputs; // Re-exports -use block_root_rollup_inputs::BlockRootRollupInputs; -use crate::abis::block_root_or_block_merge_public_inputs::BlockRootOrBlockMergePublicInputs; +pub use block_root_rollup_inputs::BlockRootRollupInputs; +pub use crate::abis::block_root_or_block_merge_public_inputs::BlockRootOrBlockMergePublicInputs; mod tests { use crate::tests::block_root_rollup_inputs::default_block_root_rollup_inputs; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr index 44012b0ed79..d787969abd2 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr @@ -11,13 +11,12 @@ use dep::types::{ merkle_tree::VariableMerkleTree, constants::{ MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, - utils::{uint256::U256, arrays::{array_length, array_merge}}, + utils::{arrays::{array_length, array_merge}}, abis::{ - append_only_tree_snapshot::AppendOnlyTreeSnapshot, accumulated_data::CombinedAccumulatedData, - public_data_update_request::PublicDataUpdateRequest, log_hash::{LogHash, ScopedLogHash} + accumulated_data::CombinedAccumulatedData, public_data_update_request::PublicDataUpdateRequest, + log_hash::{LogHash, ScopedLogHash} } }; @@ -25,7 +24,10 @@ use dep::types::{ * Asserts that the tree formed by rollup circuits is filled greedily from L to R * */ -pub fn assert_txs_filled_from_left(left: BaseOrMergeRollupPublicInputs, right: BaseOrMergeRollupPublicInputs) { +pub fn assert_txs_filled_from_left( + left: BaseOrMergeRollupPublicInputs, + right: BaseOrMergeRollupPublicInputs +) { // assert that the left rollup is either a base (1 tx) or a balanced tree (num txs = power of 2) if (left.rollup_type == 1) { let left_txs = left.num_txs; @@ -48,7 +50,10 @@ pub fn assert_txs_filled_from_left(left: BaseOrMergeRollupPublicInputs, right: B * Asserts that the constants used in the left and right child are identical * */ -pub fn assert_equal_constants(left: BaseOrMergeRollupPublicInputs, right: BaseOrMergeRollupPublicInputs) { +pub fn assert_equal_constants( + left: BaseOrMergeRollupPublicInputs, + right: BaseOrMergeRollupPublicInputs +) { assert(left.constants.eq(right.constants), "input proofs have different constants"); } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr index 6e4bb4336a9..2aa9f12c273 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr @@ -66,12 +66,9 @@ impl MergeRollupInputs { } mod tests { - use crate::{ - merge::merge_rollup_inputs::MergeRollupInputs, - tests::merge_rollup_inputs::default_merge_rollup_inputs - }; + use crate::{tests::merge_rollup_inputs::default_merge_rollup_inputs}; use dep::types::hash::accumulate_sha256; - use dep::types::constants::{ROOT_PARITY_INDEX, MERGE_ROLLUP_INDEX, BASE_ROLLUP_INDEX}; + use dep::types::constants::{MERGE_ROLLUP_INDEX, BASE_ROLLUP_INDEX}; #[test(should_fail_with="The rollup should be filled greedily from L to R, but received a L base and R merge")] fn different_rollup_type_fails() { diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/mod.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/mod.nr index d1b7641680b..2ec68ba0487 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/mod.nr @@ -1,3 +1,4 @@ mod merge_rollup_inputs; -use merge_rollup_inputs::MergeRollupInputs; -use crate::abis::base_or_merge_rollup_public_inputs::BaseOrMergeRollupPublicInputs; + +pub use merge_rollup_inputs::MergeRollupInputs; +pub use crate::abis::base_or_merge_rollup_public_inputs::BaseOrMergeRollupPublicInputs; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/mod.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/mod.nr index c5b228f55a0..f4cff7750d2 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/mod.nr @@ -2,8 +2,8 @@ mod root_rollup_inputs; mod root_rollup_public_inputs; // Re-exports -use root_rollup_inputs::RootRollupInputs; -use root_rollup_public_inputs::RootRollupPublicInputs; +pub use root_rollup_inputs::RootRollupInputs; +pub use root_rollup_public_inputs::RootRollupPublicInputs; mod tests { use crate::{tests::root_rollup_inputs::default_root_rollup_inputs}; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/l1_to_l2_roots.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/l1_to_l2_roots.nr index c15acb6695e..34b7cf47b72 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/l1_to_l2_roots.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/l1_to_l2_roots.nr @@ -1,6 +1,6 @@ use dep::types::constants::ROOT_PARITY_INDEX; use dep::types::tests::fixtures; -use dep::parity_lib::{root::root_rollup_parity_input::RootRollupParityInput, ParityPublicInputs}; +use dep::parity_lib::{root::root_rollup_parity_input::RootRollupParityInput}; pub fn default_root_rollup_parity_input() -> RootRollupParityInput { let mut input = RootRollupParityInput::empty(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data.nr index 2e8ec3cef79..fc48dc3c0e5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data.nr @@ -4,10 +4,8 @@ mod private_accumulated_data_builder; mod public_accumulated_data; mod public_accumulated_data_builder; -use crate::abis::accumulated_data::{ - combined_accumulated_data::CombinedAccumulatedData, - private_accumulated_data::PrivateAccumulatedData, - private_accumulated_data_builder::PrivateAccumulatedDataBuilder, - public_accumulated_data::PublicAccumulatedData, - public_accumulated_data_builder::PublicAccumulatedDataBuilder -}; +pub use combined_accumulated_data::CombinedAccumulatedData; +pub use private_accumulated_data::PrivateAccumulatedData; +pub use private_accumulated_data_builder::PrivateAccumulatedDataBuilder; +pub use public_accumulated_data::PublicAccumulatedData; +pub use public_accumulated_data_builder::PublicAccumulatedDataBuilder; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr index 5c8b35cc472..ab74f51e033 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr @@ -1,10 +1,10 @@ use crate::{ abis::{ - gas::Gas, note_hash::ScopedNoteHash, nullifier::ScopedNullifier, - private_call_request::PrivateCallRequest, public_call_request::PublicCallRequest, + note_hash::ScopedNoteHash, nullifier::ScopedNullifier, private_call_request::PrivateCallRequest, + public_call_request::PublicCallRequest, log_hash::{ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash} }, - traits::{Serialize, Deserialize, Eq, Empty}, messaging::l2_to_l1_message::ScopedL2ToL1Message, + traits::{Serialize, Deserialize, Empty}, messaging::l2_to_l1_message::ScopedL2ToL1Message, utils::reader::Reader }; use crate::constants::{ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index 7ea6e0402fc..7b02b2c5c28 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -8,8 +8,7 @@ use crate::{ constants::{ MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, DA_GAS_PER_BYTE, L2_GAS_PER_LOG_BYTE, - L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, FIXED_AVM_STARTUP_L2_GAS + MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::Empty }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr index 0367a9d9673..732571f90bb 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr @@ -1,8 +1,7 @@ use crate::{ abis::{ public_data_update_request::PublicDataUpdateRequest, gas::Gas, note_hash::ScopedNoteHash, - nullifier::Nullifier, log_hash::{LogHash, ScopedLogHash, NoteLogHash}, - public_call_request::PublicCallRequest + nullifier::Nullifier, log_hash::{LogHash, ScopedLogHash}, public_call_request::PublicCallRequest }, messaging::l2_to_l1_message::ScopedL2ToL1Message, constants::{ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr index 8a44667de99..2488befe838 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr @@ -2,7 +2,7 @@ use crate::{ abis::{ gas::Gas, accumulated_data::public_accumulated_data::PublicAccumulatedData, note_hash::ScopedNoteHash, nullifier::Nullifier, public_call_request::PublicCallRequest, - public_data_update_request::PublicDataUpdateRequest, log_hash::{LogHash, NoteLogHash, ScopedLogHash} + public_data_update_request::PublicDataUpdateRequest, log_hash::{LogHash, ScopedLogHash} }, messaging::l2_to_l1_message::ScopedL2ToL1Message, constants::{ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr index 3e24b2188c1..5969d30fbf4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr @@ -1,7 +1,6 @@ use crate::{ - abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, - constants::{GAS_LENGTH, FIXED_DA_GAS, FIXED_L2_GAS}, traits::{Deserialize, Hash, Serialize, Empty}, - abis::side_effect::Ordered, utils::reader::Reader, abis::gas_fees::GasFees + constants::{GAS_LENGTH, FIXED_DA_GAS, FIXED_L2_GAS}, traits::{Deserialize, Serialize, Empty}, + abis::gas_fees::GasFees }; use std::ops::{Add, Sub}; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr index 01fc730ee01..90a7e1fb426 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr @@ -1,8 +1,4 @@ -use crate::{ - abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, - constants::GAS_FEES_LENGTH, traits::{Deserialize, Hash, Serialize, Empty}, - abis::side_effect::Ordered, utils::reader::Reader -}; +use crate::{constants::GAS_FEES_LENGTH, traits::{Deserialize, Serialize, Empty}}; struct GasFees { fee_per_da_gas: Field, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr index 4460c71bb31..11126ce25e3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr @@ -1,11 +1,10 @@ use crate::{ - abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas, - abis::gas_fees::GasFees, + abis::{gas::Gas, gas_fees::GasFees}, constants::{ GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS, DEFAULT_INCLUSION_FEE }, - traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader + traits::{Deserialize, Serialize, Empty}, utils::reader::Reader }; struct GasSettings { @@ -57,7 +56,7 @@ impl Serialize for GasSettings { serialized.extend_from_array(self.teardown_gas_limits.serialize()); serialized.extend_from_array(self.max_fees_per_gas.serialize()); serialized.push(self.inclusion_fee); - + serialized.storage } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr index 471abce4366..05b59ff38a1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr @@ -1,7 +1,6 @@ use crate::{ - address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees, - constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH}, - traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader + address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees, constants::GLOBAL_VARIABLES_LENGTH, + traits::{Deserialize, Empty, Serialize}, utils::reader::Reader }; // docs:start:global-variables @@ -72,7 +71,7 @@ impl Eq for GlobalVariables { (self.timestamp == other.timestamp) & (self.coinbase == other.coinbase) & (self.fee_recipient == other.fee_recipient) & - (self.gas_fees == other.gas_fees) + (self.gas_fees == other.gas_fees) } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs.nr deleted file mode 100644 index c1b3a7dd0ca..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs.nr +++ /dev/null @@ -1,13 +0,0 @@ -mod kernel_circuit_public_inputs; -mod private_kernel_circuit_public_inputs; -mod private_kernel_circuit_public_inputs_builder; -mod public_kernel_circuit_public_inputs; -mod public_kernel_circuit_public_inputs_builder; - -use crate::abis::kernel_circuit_public_inputs::{ - kernel_circuit_public_inputs::KernelCircuitPublicInputs, - private_kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsArrayLengths}, - private_kernel_circuit_public_inputs_builder::PrivateKernelCircuitPublicInputsBuilder, - public_kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - public_kernel_circuit_public_inputs_builder::PublicKernelCircuitPublicInputsBuilder -}; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr index ef4e556ef2d..71b37b8dffa 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr @@ -1,10 +1,10 @@ use crate::{ abis::{ accumulated_data::CombinedAccumulatedData, combined_constant_data::CombinedConstantData, - validation_requests::RollupValidationRequests, gas::Gas, gas_fees::GasFees + validation_requests::RollupValidationRequests, gas_fees::GasFees }, address::AztecAddress, partial_state_reference::PartialStateReference, - traits::{Empty, Eq, Serialize, Deserialize}, constants::KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH, + traits::{Empty, Serialize, Deserialize}, constants::KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH, utils::reader::Reader }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/mod.nr new file mode 100644 index 00000000000..d30b2feeea2 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/mod.nr @@ -0,0 +1,11 @@ +mod kernel_circuit_public_inputs; +mod private_kernel_circuit_public_inputs; +mod private_kernel_circuit_public_inputs_builder; +mod public_kernel_circuit_public_inputs; +mod public_kernel_circuit_public_inputs_builder; + +pub use kernel_circuit_public_inputs::KernelCircuitPublicInputs; +pub use private_kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsArrayLengths}; +pub use private_kernel_circuit_public_inputs_builder::PrivateKernelCircuitPublicInputsBuilder; +pub use public_kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs; +pub use public_kernel_circuit_public_inputs_builder::PublicKernelCircuitPublicInputsBuilder; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr index 525aaba4dc2..f02854b6815 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr @@ -1,11 +1,11 @@ -use crate::abis::{ +use crate::{ + abis::{ accumulated_data::PrivateAccumulatedData, combined_constant_data::CombinedConstantData, public_call_request::PublicCallRequest, validation_requests::PrivateValidationRequests +}, + address::AztecAddress, constants::PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH, + traits::{Serialize, Deserialize, Empty}, utils::{arrays::array_length, reader::Reader} }; -use crate::constants::PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH; -use crate::traits::{Serialize, Deserialize, Eq, Empty}; -use crate::utils::{arrays::array_length, reader::Reader}; -use crate::address::AztecAddress; struct PrivateKernelCircuitPublicInputsArrayLengths { note_hash_read_requests: u32, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs.nr index c9903d28e68..8bc2692a719 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs.nr @@ -1,12 +1,12 @@ -use crate::abis::{ +use crate::{ + abis::{ accumulated_data::PublicAccumulatedData, combined_constant_data::CombinedConstantData, - public_call_request::PublicCallRequest, - validation_requests::{RollupValidationRequests, PublicValidationRequests} + public_call_request::PublicCallRequest, validation_requests::PublicValidationRequests +}, + address::AztecAddress, + constants::{MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH}, + traits::{Empty, Serialize, Deserialize}, utils::reader::Reader }; -use crate::constants::{MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH}; -use crate::traits::{Empty, Serialize, Deserialize, Eq}; -use crate::utils::reader::Reader; -use crate::address::AztecAddress; struct PublicKernelCircuitPublicInputs { validation_requests: PublicValidationRequests, @@ -47,7 +47,6 @@ impl Serialize for PublicKernelCircu } fields.extend_from_array(self.fee_payer.serialize()); - assert_eq(fields.len(), PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr index 263b4fc8494..eaf5f67baf5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr @@ -1,7 +1,6 @@ use crate::{ abis::{ - accumulated_data::{CombinedAccumulatedData, PublicAccumulatedDataBuilder}, - combined_constant_data::CombinedConstantData, + accumulated_data::PublicAccumulatedDataBuilder, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{public_kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs}, public_call_request::PublicCallRequest, validation_requests::PublicValidationRequestsBuilder }, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr index 6f7b04eda6e..deb99b2911b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr @@ -1,8 +1,9 @@ -use crate::constants::VK_TREE_HEIGHT; -use crate::abis::kernel_circuit_public_inputs::KernelCircuitPublicInputs; -use crate::recursion::{proof::NestedRecursiveProof, verification_key::VerificationKey, traits::Verifiable}; -use crate::merkle_tree::membership::assert_check_membership; -use crate::utils::arrays::find_index_hint; +use crate::{ + abis::kernel_circuit_public_inputs::KernelCircuitPublicInputs, constants::VK_TREE_HEIGHT, + merkle_tree::membership::assert_check_membership, + recursion::{proof::NestedRecursiveProof, verification_key::VerificationKey, traits::Verifiable}, + utils::arrays::find_index_hint +}; struct KernelData { public_inputs: KernelCircuitPublicInputs, @@ -26,7 +27,9 @@ impl Verifiable for KernelData { impl KernelData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { - let index_hint = find_index_hint(allowed_indices, |index: u32| index == self.vk_index); + let index_hint = unsafe { + find_index_hint(allowed_indices, |index: u32| index == self.vk_index) + }; assert_eq(allowed_indices[index_hint], self.vk_index, "Invalid vk index"); assert_check_membership( diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr index 72738cbdf81..87f44a23b0c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr @@ -20,6 +20,7 @@ mod note_hash; mod nullifier; mod public_data_read; mod public_data_update_request; +mod public_data_write; mod accumulated_data; mod validation_requests; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr index 9bb1a681298..2b0504a745b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr @@ -19,7 +19,7 @@ impl Ordered for NoteHash { impl Eq for NoteHash { fn eq(self, other: NoteHash) -> bool { (self.value == other.value) - & (self.counter == other.counter) + & (self.counter == other.counter) } } @@ -116,7 +116,7 @@ impl Deserialize for ScopedNoteHash { } } -impl Readable for ScopedNoteHash { +impl Readable for ScopedNoteHash { fn assert_match_read_request(self, read_request: ScopedReadRequest) { assert_eq(self.note_hash.value, read_request.value(), "Value of the note hash does not match read request"); assert_eq(self.contract_address, read_request.contract_address, "Contract address of the note hash does not match read request"); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr index e1a933e2644..7fa6b73e174 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr @@ -2,7 +2,7 @@ global NOTE_HASH_LEAF_PREIMAGE_LENGTH: u64 = 1; use crate::{ abis::{read_request::ScopedReadRequest, side_effect::Readable}, hash::compute_siloed_note_hash, - merkle_tree::leaf_preimage::LeafPreimage, traits::{Empty, Hash, Eq} + merkle_tree::leaf_preimage::LeafPreimage, traits::Empty }; struct NoteHashLeafPreimage { @@ -27,7 +27,7 @@ impl LeafPreimage for NoteHashLeafPreimage { } } -impl Readable for NoteHashLeafPreimage { +impl Readable for NoteHashLeafPreimage { fn assert_match_read_request(self, read_request: ScopedReadRequest) { let siloed_value = compute_siloed_note_hash(read_request.contract_address, read_request.value()); assert_eq(self.value, siloed_value, "Value of the note hash leaf does not match read request"); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr index 62d44ab9d63..f31a0658f6b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr @@ -1,7 +1,7 @@ use crate::{ abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest}, address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH}, - hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize}, + hash::compute_siloed_nullifier, traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader} }; @@ -30,7 +30,7 @@ impl Eq for Nullifier { fn eq(self, other: Nullifier) -> bool { (self.value == other.value) & (self.counter == other.counter) - & (self.note_hash == other.note_hash) + & (self.note_hash == other.note_hash) } } @@ -60,7 +60,7 @@ impl Deserialize for Nullifier { } } -impl Readable for Nullifier { +impl Readable for Nullifier { fn assert_match_read_request(self, read_request: ScopedReadRequest) { // Public kernels output Nullifier instead of ScopedNullifier. // The nullifier value has been siloed. @@ -110,7 +110,7 @@ impl OrderedValue for ScopedNullifier { impl Eq for ScopedNullifier { fn eq(self, other: ScopedNullifier) -> bool { (self.nullifier == other.nullifier) - & (self.contract_address == other.contract_address) + & (self.contract_address == other.contract_address) } } @@ -141,7 +141,7 @@ impl Deserialize for ScopedNullifier { } } -impl Readable for ScopedNullifier { +impl Readable for ScopedNullifier { fn assert_match_read_request(self, read_request: ScopedReadRequest) { assert_eq(self.nullifier.value, read_request.value(), "Value of the nullifier does not match read request"); assert_eq(self.contract_address, read_request.contract_address, "Contract address of the nullifier does not match read request"); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr index c6ce3f9bad0..835510584b9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr @@ -55,7 +55,7 @@ impl IndexedTreeLeafPreimage for NullifierLeafPreimage { } } -impl Readable for NullifierLeafPreimage { +impl Readable for NullifierLeafPreimage { fn assert_match_read_request(self, read_request: ScopedReadRequest) { let siloed_value = compute_siloed_nullifier(read_request.contract_address, read_request.value()); assert_eq(self.nullifier, siloed_value, "Value of the nullifier leaf does not match read request"); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index a207b68842f..97ab5675046 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -1,6 +1,6 @@ use crate::{ abis::{ - call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings, + call_context::CallContext, max_block_number::MaxBlockNumber, validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier, private_call_request::PrivateCallRequest, public_call_request::PublicCallRequest, read_request::ReadRequest, log_hash::{LogHash, NoteLogHash, EncryptedLogHash} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr index b9064f8b561..512d114dbc6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr @@ -1,11 +1,7 @@ use crate::{ - abis::{ - private_call_stack_item::PrivateCallStackItem, - private_circuit_public_inputs::PrivateCircuitPublicInputs -}, - address::{SaltedInitializationHash, PublicKeysHash, EthAddress}, constants::FUNCTION_TREE_HEIGHT, - contract_class_id::ContractClassId, merkle_tree::membership::MembershipWitness, - recursion::{verification_key::VerificationKey, proof::RecursiveProof, traits::Verifiable} + abis::{private_call_stack_item::PrivateCallStackItem}, + address::{SaltedInitializationHash, PublicKeysHash}, constants::FUNCTION_TREE_HEIGHT, + merkle_tree::membership::MembershipWitness, recursion::{verification_key::VerificationKey} }; struct PrivateCallData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr index 4408555bedc..623ef5f1cad 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr @@ -1,8 +1,8 @@ -use crate::recursion::{verification_key::VerificationKey, proof::NestedRecursiveProof, traits::Verifiable}; -use crate::constants::VK_TREE_HEIGHT; -use crate::abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs; -use crate::merkle_tree::membership::assert_check_membership; -use crate::utils::arrays::find_index_hint; +use crate::{ + abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, constants::VK_TREE_HEIGHT, + merkle_tree::membership::assert_check_membership, recursion::{verification_key::VerificationKey}, + utils::arrays::find_index_hint +}; struct PrivateKernelData { public_inputs: PrivateKernelCircuitPublicInputs, @@ -17,7 +17,9 @@ struct PrivateKernelData { impl PrivateKernelData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { - let index_hint = find_index_hint(allowed_indices, |index: u32| index == self.vk_index); + let index_hint = unsafe { + find_index_hint(allowed_indices, |index: u32| index == self.vk_index) + }; assert_eq(allowed_indices[index_hint], self.vk_index, "Invalid vk index"); assert_check_membership( diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr index fa8f27b781a..b5cfb29fadc 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr @@ -1,7 +1,7 @@ use crate::{ abis::{public_call_stack_item_compressed::PublicCallStackItemCompressed, side_effect::Ordered}, - address::AztecAddress, constants::PUBLIC_CALL_REQUEST_LENGTH, - traits::{Empty, Serialize, Deserialize}, utils::reader::Reader + constants::PUBLIC_CALL_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize}, + utils::reader::Reader }; struct PublicCallRequest { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr index 0d12098c4f5..3cceed1ad15 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr @@ -1,59 +1,57 @@ -use crate::constants::{GENERATOR_INDEX__PUBLIC_DATA_READ, PUBLIC_DATA_READ_LENGTH}; -use crate::traits::{Empty, Hash, Serialize, Deserialize}; -use crate::contrakt::storage_read::StorageRead; -use crate::data::hash::{compute_public_data_tree_value, compute_public_data_tree_index}; -use crate::address::AztecAddress; +use crate::{ + abis::side_effect::Ordered, address::AztecAddress, constants::PUBLIC_DATA_READ_LENGTH, + contrakt::storage_read::StorageRead, + data::hash::{compute_public_data_tree_value, compute_public_data_tree_index}, + traits::{Empty, Serialize, Deserialize} +}; struct PublicDataRead { - leaf_slot : Field, - value : Field, + leaf_slot: Field, + value: Field, + counter: u32, } impl PublicDataRead { - pub fn from_contract_storage_read( - contract_address: AztecAddress, - read_request: StorageRead - ) -> PublicDataRead { + pub fn from_contract_storage_read(contract_address: AztecAddress, read_request: StorageRead) -> PublicDataRead { PublicDataRead { leaf_slot: compute_public_data_tree_index(contract_address, read_request.storage_slot), - value: compute_public_data_tree_value(read_request.current_value) + value: compute_public_data_tree_value(read_request.current_value), + counter: read_request.counter } } } impl Eq for PublicDataRead { - fn eq(self, public_data_read: PublicDataRead) -> bool { - (public_data_read.leaf_slot == self.leaf_slot) & (public_data_read.value == self.value) + fn eq(self, other: PublicDataRead) -> bool { + (other.leaf_slot == self.leaf_slot) & (other.value == self.value) & (other.counter == self.counter) } } impl Empty for PublicDataRead { fn empty() -> Self { Self { - leaf_slot : 0, - value : 0, + leaf_slot: 0, + value: 0, + counter: 0, } } } -impl Hash for PublicDataRead { - fn hash(self) -> Field { - crate::hash::poseidon2_hash_with_separator([ - self.leaf_slot, - self.value, - ], GENERATOR_INDEX__PUBLIC_DATA_READ) +impl Ordered for PublicDataRead { + fn counter(self) -> u32 { + self.counter } } impl PublicDataRead { pub fn is_empty(self) -> bool { - (self.leaf_slot == 0) & (self.value == 0) + (self.leaf_slot == 0) & (self.value == 0) & (self.counter == 0) } } impl Serialize for PublicDataRead { fn serialize(self) -> [Field; PUBLIC_DATA_READ_LENGTH] { - [self.leaf_slot, self.value] + [self.leaf_slot, self.value, self.counter as Field] } } @@ -62,6 +60,7 @@ impl Deserialize for PublicDataRead { PublicDataRead { leaf_slot: fields[0], value: fields[1], + counter: fields[2] as u32, } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr index ac0d0738915..367e8a9db1f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr @@ -1,11 +1,14 @@ -use crate::constants::{PUBLIC_DATA_UPDATE_REQUEST_LENGTH, GENERATOR_INDEX__PUBLIC_DATA_UPDATE_REQUEST}; -use crate::traits::{Empty, Hash, Serialize, Deserialize}; -use crate::public_data_tree_leaf::PublicDataTreeLeaf; -use crate::address::AztecAddress; -use crate::contrakt::storage_update_request::StorageUpdateRequest; -use crate::data::hash::{compute_public_data_tree_value, compute_public_data_tree_index}; -use crate::abis::side_effect::{Ordered, Positioned}; +use crate::{ + abis::{side_effect::Ordered}, address::AztecAddress, constants::PUBLIC_DATA_UPDATE_REQUEST_LENGTH, + contrakt::storage_update_request::StorageUpdateRequest, + data::{ + hash::{compute_public_data_tree_value, compute_public_data_tree_index}, + public_data_tree_leaf::PublicDataTreeLeaf +}, + traits::{Empty, Serialize, Deserialize} +}; +// TODO: Rename to PublicDataWrite struct PublicDataUpdateRequest { leaf_slot : Field, new_value : Field, @@ -25,12 +28,6 @@ impl PublicDataUpdateRequest { } } -impl Positioned for PublicDataUpdateRequest { - fn position(self) -> Field { - self.leaf_slot - } -} - impl Ordered for PublicDataUpdateRequest { fn counter(self)-> u32{ self.counter @@ -54,15 +51,6 @@ impl Empty for PublicDataUpdateRequest { } } -impl Hash for PublicDataUpdateRequest { - fn hash(self) -> Field { - crate::hash::poseidon2_hash_with_separator([ - self.leaf_slot, - self.new_value - ], GENERATOR_INDEX__PUBLIC_DATA_UPDATE_REQUEST) - } -} - impl From for PublicDataTreeLeaf { fn from(update_request: PublicDataUpdateRequest) -> PublicDataTreeLeaf { PublicDataTreeLeaf { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_write.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_write.nr new file mode 100644 index 00000000000..251d31a1af6 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_write.nr @@ -0,0 +1,52 @@ +use crate::{ + abis::{ + public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, + side_effect::{Inner, Ordered, Overridable, Readable} +}, + traits::Empty +}; + +struct OverridablePublicDataWrite { + write: PublicDataUpdateRequest, + override_counter: u32, +} + +impl Eq for OverridablePublicDataWrite { + fn eq(self, other: OverridablePublicDataWrite) -> bool { + (other.write == self.write) & (other.override_counter == self.override_counter) + } +} + +impl Empty for OverridablePublicDataWrite { + fn empty() -> Self { + Self { + write: PublicDataUpdateRequest::empty(), + override_counter: 0, + } + } +} + +impl Ordered for OverridablePublicDataWrite { + fn counter(self)-> u32{ + self.write.counter() + } +} + +impl Readable for OverridablePublicDataWrite { + fn assert_match_read_request(self, read_request: PublicDataRead) { + assert_eq(self.write.leaf_slot, read_request.leaf_slot, "leaf_slot in OverridablePublicDataWrite does not match read request"); + assert_eq(self.write.new_value, read_request.value, "value in OverridablePublicDataWrite does not match read request"); + } +} + +impl Overridable for OverridablePublicDataWrite { + fn override_counter(self) -> u32 { + self.override_counter + } +} + +impl Inner for OverridablePublicDataWrite { + fn inner(self) -> PublicDataUpdateRequest { + self.write + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr index 655378288fd..fd739fa45a3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr @@ -1,8 +1,9 @@ -use crate::constants::VK_TREE_HEIGHT; -use crate::abis::kernel_circuit_public_inputs::{PublicKernelCircuitPublicInputs, KernelCircuitPublicInputs}; -use crate::recursion::{proof::NestedRecursiveProof, verification_key::VerificationKey, traits::Verifiable}; -use crate::merkle_tree::membership::assert_check_membership; -use crate::utils::arrays::find_index_hint; +use crate::{ + abis::kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, constants::VK_TREE_HEIGHT, + merkle_tree::membership::assert_check_membership, + recursion::{proof::NestedRecursiveProof, verification_key::VerificationKey, traits::Verifiable}, + utils::arrays::find_index_hint +}; struct PublicKernelData { public_inputs: PublicKernelCircuitPublicInputs, @@ -26,7 +27,9 @@ impl Verifiable for PublicKernelData { impl PublicKernelData { fn validate_in_vk_tree(self, allowed_indices: [u32; N]) { - let index_hint = find_index_hint(allowed_indices, |index: u32| index == self.vk_index); + let index_hint = unsafe { + find_index_hint(allowed_indices, |index: u32| index == self.vk_index) + }; assert_eq(allowed_indices[index_hint], self.vk_index, "Invalid vk index"); assert_check_membership( diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr index e888e6a3fbd..ac98426ae34 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr @@ -1,4 +1,4 @@ -use crate::{abis::read_request::ScopedReadRequest, address::AztecAddress}; +use crate::{address::AztecAddress}; trait Ordered { fn counter(self) -> u32; @@ -19,12 +19,15 @@ trait Scoped where T: Eq { fn inner(self) -> T; } -trait Positioned { - // Like a storage slot - fn position(self) -> Field; +trait Readable { + fn assert_match_read_request(self, read_request: T); } -trait Readable { - fn assert_match_read_request(self, read_request: ScopedReadRequest); +trait Overridable { + // The counter of the next side effect that's overriding the current side effect. + fn override_counter(self) -> u32; } +trait Inner { + fn inner(self) -> T; +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/mod.nr index 74eaf16f8bb..7470eeb30f9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/mod.nr @@ -7,11 +7,11 @@ mod public_validation_requests_builder; mod rollup_validation_requests; mod scoped_key_validation_request_and_generator; -use key_validation_request::KeyValidationRequest; -use key_validation_request_and_generator::KeyValidationRequestAndGenerator; -use private_validation_requests::PrivateValidationRequests; -use private_validation_requests_builder::PrivateValidationRequestsBuilder; -use public_validation_requests::PublicValidationRequests; -use public_validation_requests_builder::PublicValidationRequestsBuilder; -use rollup_validation_requests::RollupValidationRequests; -use scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator; +pub use key_validation_request::KeyValidationRequest; +pub use key_validation_request_and_generator::KeyValidationRequestAndGenerator; +pub use private_validation_requests::PrivateValidationRequests; +pub use private_validation_requests_builder::PrivateValidationRequestsBuilder; +pub use public_validation_requests::PublicValidationRequests; +pub use public_validation_requests_builder::PublicValidationRequestsBuilder; +pub use rollup_validation_requests::RollupValidationRequests; +pub use scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr index daa30dc0f82..0f81993be85 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr @@ -1,8 +1,8 @@ use crate::{ - crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash}, + crate::address::{partial_address::PartialAddress, public_keys_hash::PublicKeysHash}, constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1}, - contract_class_id::ContractClassId, hash::poseidon2_hash_with_separator, - traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils + hash::poseidon2_hash_with_separator, traits::{Empty, FromField, ToField, Serialize, Deserialize}, + utils }; // Aztec address diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/mod.nr index 636a6b26578..9c7a400ea9c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/mod.nr @@ -4,11 +4,11 @@ mod partial_address; mod public_keys_hash; mod salted_initialization_hash; -use crate::address::aztec_address::AztecAddress; -use crate::address::eth_address::EthAddress; -use crate::address::partial_address::PartialAddress; -use crate::address::public_keys_hash::PublicKeysHash; -use crate::address::salted_initialization_hash::SaltedInitializationHash; +pub use aztec_address::AztecAddress; +pub use eth_address::EthAddress; +pub use partial_address::PartialAddress; +pub use public_keys_hash::PublicKeysHash; +pub use salted_initialization_hash::SaltedInitializationHash; use crate::{constants::GENERATOR_INDEX__CONSTRUCTOR, hash::poseidon2_hash_with_separator}; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr index ae8d8ee73cf..148df7d70bf 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr @@ -1,10 +1,7 @@ use crate::{ - address::{ - eth_address::EthAddress, salted_initialization_hash::SaltedInitializationHash, - aztec_address::AztecAddress -}, + address::{salted_initialization_hash::SaltedInitializationHash, aztec_address::AztecAddress}, constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId, - hash::poseidon2_hash_with_separator, traits::{ToField, FromField, Serialize, Deserialize} + hash::poseidon2_hash_with_separator, traits::{ToField, Serialize, Deserialize} }; global PARTIAL_ADDRESS_LENGTH = 1; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr index 1b04dec19eb..07fc4dc215b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr @@ -1,6 +1,6 @@ use crate::{ - address::{eth_address::EthAddress, aztec_address::AztecAddress}, - constants::GENERATOR_INDEX__PARTIAL_ADDRESS, hash::poseidon2_hash_with_separator, traits::ToField + address::{aztec_address::AztecAddress}, constants::GENERATOR_INDEX__PARTIAL_ADDRESS, + hash::poseidon2_hash_with_separator, traits::ToField }; // Salted initialization hash. Used in the computation of a partial address. diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index a0c586fa911..45d5b997272 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -135,7 +135,7 @@ global INITIAL_L2_BLOCK_NUM: Field = 1; global BLOB_SIZE_IN_BYTES: Field = 31 * 4096; global ETHEREUM_SLOT_DURATION: u32 = 12; // AZTEC_SLOT_DURATION should be a multiple of ETHEREUM_SLOT_DURATION -global AZTEC_SLOT_DURATION: u32 = ETHEREUM_SLOT_DURATION * 1; +global AZTEC_SLOT_DURATION: u32 = ETHEREUM_SLOT_DURATION * 3; global AZTEC_EPOCH_DURATION: u32 = 48; global AZTEC_TARGET_COMMITTEE_SIZE: u32 = 48; // The following is taken from building a block and looking at the `lastArchive` value in it. @@ -249,7 +249,7 @@ global PUBLIC_CONTEXT_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + HEADER_LENGTH + global AGGREGATION_OBJECT_LENGTH: u32 = 16; global SCOPED_READ_REQUEST_LEN = READ_REQUEST_LENGTH + 1; -global PUBLIC_DATA_READ_LENGTH = 2; +global PUBLIC_DATA_READ_LENGTH = 3; global PRIVATE_VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + (SCOPED_READ_REQUEST_LEN * MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) + (SCOPED_KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_TX) + 2; global PUBLIC_VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + (TREE_LEAF_READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX) + (TREE_LEAF_READ_REQUEST_LENGTH * MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX); @@ -432,11 +432,8 @@ global AVM_CHAINID_BASE_L2_GAS: u16 = 200; global AVM_VERSION_BASE_L2_GAS: u16 = 200; global AVM_BLOCKNUMBER_BASE_L2_GAS: u16 = 200; global AVM_TIMESTAMP_BASE_L2_GAS: u16 = 200; -global AVM_COINBASE_BASE_L2_GAS: u16 = 200; global AVM_FEEPERL2GAS_BASE_L2_GAS: u16 = 200; global AVM_FEEPERDAGAS_BASE_L2_GAS: u16 = 200; -global AVM_BLOCKL2GASLIMIT_BASE_L2_GAS: u16 = 200; -global AVM_BLOCKDAGASLIMIT_BASE_L2_GAS: u16 = 200; global AVM_CALLDATACOPY_BASE_L2_GAS: u16 = 290; global AVM_L2GASLEFT_BASE_L2_GAS: u16 = 180; global AVM_DAGASLEFT_BASE_L2_GAS: u16 = 180; @@ -498,11 +495,8 @@ global AVM_CHAINID_DYN_L2_GAS: u16 = 0; global AVM_VERSION_DYN_L2_GAS: u16 = 0; global AVM_BLOCKNUMBER_DYN_L2_GAS: u16 = 0; global AVM_TIMESTAMP_DYN_L2_GAS: u16 = 0; -global AVM_COINBASE_DYN_L2_GAS: u16 = 0; global AVM_FEEPERL2GAS_DYN_L2_GAS: u16 = 0; global AVM_FEEPERDAGAS_DYN_L2_GAS: u16 = 0; -global AVM_BLOCKL2GASLIMIT_DYN_L2_GAS: u16 = 0; -global AVM_BLOCKDAGASLIMIT_DYN_L2_GAS: u16 = 0; global AVM_CALLDATACOPY_DYN_L2_GAS: u16 = 50; global AVM_L2GASLEFT_DYN_L2_GAS: u16 = 0; global AVM_DAGASLEFT_DYN_L2_GAS: u16 = 0; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr b/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr index bc1b421134c..aaac9302864 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr @@ -1,7 +1,4 @@ -use crate::{ - constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize}, - utils::arr_copy_slice -}; +use crate::{constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Serialize}}; struct ContentCommitment { num_txs: Field, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr index 32b52180d58..365d7141532 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr @@ -1,5 +1,5 @@ use crate::constants::GENERATOR_INDEX__CONTRACT_LEAF; -use crate::traits::{ToField, FromField, Hash, Serialize, Deserialize}; +use crate::traits::{ToField, FromField, Serialize, Deserialize}; struct ContractClassId { inner: Field diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr index 1780cbd12ab..6d22a482b76 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr @@ -1,10 +1,6 @@ use crate::{ - address::{ - aztec_address::AztecAddress, eth_address::EthAddress, partial_address::PartialAddress, - public_keys_hash::PublicKeysHash -}, - contract_class_id::ContractClassId, - constants::{GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA, CONTRACT_INSTANCE_LENGTH}, + address::{aztec_address::AztecAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash}, + contract_class_id::ContractClassId, constants::CONTRACT_INSTANCE_LENGTH, traits::{Deserialize, Hash, Serialize} }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_read.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_read.nr index 6f44e699eea..6ed6251c8e3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_read.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_read.nr @@ -1,12 +1,8 @@ -use crate::{ - constants::{CONTRACT_STORAGE_READ_LENGTH, GENERATOR_INDEX__PUBLIC_DATA_READ}, - hash::poseidon2_hash_with_separator, traits::{Deserialize, Hash, Empty, Serialize} -}; +use crate::{constants::CONTRACT_STORAGE_READ_LENGTH, traits::{Deserialize, Empty, Serialize}}; struct StorageRead { storage_slot: Field, current_value: Field, - // TODO(dbanks12): use side effects properly in kernel checks counter: u32, } @@ -16,7 +12,7 @@ impl Eq for StorageRead { } } -impl Empty for StorageRead { +impl Empty for StorageRead { fn empty() -> Self { Self { storage_slot: 0, @@ -26,12 +22,6 @@ impl Empty for StorageRead { } } -impl Hash for StorageRead { - fn hash(self) -> Field { - poseidon2_hash_with_separator(self.serialize(), GENERATOR_INDEX__PUBLIC_DATA_READ) - } -} - impl Serialize for StorageRead { fn serialize(self) -> [Field; CONTRACT_STORAGE_READ_LENGTH] { [self.storage_slot, self.current_value, self.counter as Field] diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr index 569ff8f03e9..767c22f5116 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr @@ -1,7 +1,4 @@ -use crate::{ - constants::{CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH, GENERATOR_INDEX__PUBLIC_DATA_UPDATE_REQUEST}, - hash::poseidon2_hash_with_separator, traits::{Deserialize, Hash, Empty, Serialize} -}; +use crate::{constants::CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH, traits::{Deserialize, Empty, Serialize}}; struct StorageUpdateRequest { storage_slot : Field, @@ -26,12 +23,6 @@ impl Empty for StorageUpdateRequest { } } -impl Hash for StorageUpdateRequest { - fn hash(self) -> Field { - poseidon2_hash_with_separator(self.serialize(), GENERATOR_INDEX__PUBLIC_DATA_UPDATE_REQUEST) - } -} - impl Serialize for StorageUpdateRequest { fn serialize(self) -> [Field; CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH] { [self.storage_slot, self.new_value, self.counter as Field] diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/data/leaf_data_hint.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/leaf_data_hint.nr deleted file mode 100644 index 198dc744ec7..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/data/leaf_data_hint.nr +++ /dev/null @@ -1,6 +0,0 @@ -trait LeafDataHint { - fn leaf_slot(self) -> Field; - fn value(self) -> Field; - fn override_counter(self) -> u32; -} - diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/data/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/mod.nr index cf34767d6f9..ff14e4cfce7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/data/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/data/mod.nr @@ -1,3 +1,10 @@ -mod leaf_data_hint; mod public_data_hint; +mod public_data_leaf_hint; +mod public_data_tree_leaf; +mod public_data_tree_leaf_preimage; mod hash; + +pub use public_data_hint::PublicDataHint; +pub use public_data_leaf_hint::PublicDataLeafHint; +pub use public_data_tree_leaf::{OverridablePublicDataTreeLeaf, PublicDataTreeLeaf}; +pub use public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_hint.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_hint.nr index 081d677d60f..a19b9a03cf5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_hint.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_hint.nr @@ -1,6 +1,6 @@ use crate::{ - public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, data::leaf_data_hint::LeafDataHint, - traits::Empty, merkle_tree::{MembershipWitness, conditionally_assert_check_membership}, + data::public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, traits::Empty, + merkle_tree::{MembershipWitness, conditionally_assert_check_membership}, constants::PUBLIC_DATA_TREE_HEIGHT }; @@ -8,7 +8,7 @@ struct PublicDataHint { leaf_slot: Field, value: Field, override_counter: u32, - membership_witness: MembershipWitness, // Should be MembershipWitness when we can handle generics when converting to ts types. + membership_witness: MembershipWitness, leaf_preimage: PublicDataTreeLeafPreimage, } @@ -37,20 +37,6 @@ impl PublicDataHint { } } -impl LeafDataHint for PublicDataHint { - fn leaf_slot(self) -> Field { - self.leaf_slot - } - - fn value(self) -> Field { - self.value - } - - fn override_counter(self) -> u32 { - self.override_counter - } -} - impl Empty for PublicDataHint { fn empty() -> Self { PublicDataHint { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_leaf_hint.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_leaf_hint.nr new file mode 100644 index 00000000000..2d2c0becd9b --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_leaf_hint.nr @@ -0,0 +1,18 @@ +use crate::{ + data::public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, traits::Empty, + merkle_tree::MembershipWitness, constants::PUBLIC_DATA_TREE_HEIGHT +}; + +struct PublicDataLeafHint { + preimage: PublicDataTreeLeafPreimage, + membership_witness: MembershipWitness, +} + +impl Empty for PublicDataLeafHint { + fn empty() -> Self { + PublicDataLeafHint { + preimage: PublicDataTreeLeafPreimage::empty(), + membership_witness: MembershipWitness::empty(), + } + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf.nr new file mode 100644 index 00000000000..d1149066df9 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf.nr @@ -0,0 +1,55 @@ +use crate::{abis::{public_data_read::PublicDataRead, side_effect::{Overridable, Readable}}, traits::Empty}; + +struct PublicDataTreeLeaf { + slot: Field, + value: Field, +} + +impl Eq for PublicDataTreeLeaf { + fn eq(self, other: Self) -> bool { + (self.slot == other.slot) & (self.value == other.value) + } +} + +impl Empty for PublicDataTreeLeaf { + fn empty() -> Self { + Self { + slot: 0, + value: 0, + } + } +} + +impl PublicDataTreeLeaf { + pub fn is_empty(self) -> bool { + (self.slot == 0) & (self.value == 0) + } +} + +struct OverridablePublicDataTreeLeaf { + leaf: PublicDataTreeLeaf, + override_counter: u32, +} + +impl Empty for OverridablePublicDataTreeLeaf { + fn empty() -> Self { + OverridablePublicDataTreeLeaf { + leaf: PublicDataTreeLeaf::empty(), + override_counter: 0, + } + } +} + +impl Readable for OverridablePublicDataTreeLeaf { + fn assert_match_read_request(self, read_request: PublicDataRead) { + assert_eq(self.leaf.slot, read_request.leaf_slot, "leaf_slot in OverridablePublicDataTreeLeaf does not match read request"); + assert_eq(self.leaf.value, read_request.value, "value in OverridablePublicDataTreeLeaf does not match read request"); + } +} + +impl Overridable for OverridablePublicDataTreeLeaf { + fn override_counter(self) -> u32 { + self.override_counter + } +} + diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf_preimage.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf_preimage.nr diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index 67a5eb1d8d5..74c49d25d48 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -13,7 +13,7 @@ use crate::{ merkle_tree::root::root_from_sibling_path, messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message}, recursion::verification_key::VerificationKey, traits::{is_empty, ToField}, - utils::field::field_from_bytes_32_trunc, point::Point + utils::field::field_from_bytes_32_trunc }; pub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field { @@ -276,10 +276,6 @@ pub fn poseidon2_hash_with_separator( sponge.squeeze() } -pub fn pedersen_commitment(inputs: [Field; N], hash_index: u32) -> Point { - std::hash::pedersen_commitment_with_separator(inputs, hash_index) -} - #[test] fn smoke_sha256_to_field() { let full_buffer = [ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/header.nr b/noir-projects/noir-protocol-circuits/crates/types/src/header.nr index 96e7a04ec4a..e6f69333319 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/header.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/header.nr @@ -1,9 +1,12 @@ use crate::{ abis::{ append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH}, - global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH} + global_variables::GlobalVariables +}, + constants::{ + GENERATOR_INDEX__BLOCK_HASH, GLOBAL_VARIABLES_LENGTH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, + CONTENT_COMMITMENT_LENGTH }, - constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH}, hash::poseidon2_hash_with_separator, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize}, utils::arr_copy_slice, content_commitment::ContentCommitment diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr index 7e36c845512..c9b1e034025 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr @@ -3,9 +3,7 @@ mod address; mod debug_log; mod point; mod scalar; -// This is intentionally spelled like this -// since contract is a reserved keyword, so it cannot -// be used as an ident. +// This is intentionally spelled like this since contract is a reserved keyword, so it cannot be used as an ident. mod contrakt; mod transaction; mod abis; @@ -26,12 +24,10 @@ mod tests; mod state_reference; mod partial_state_reference; -mod public_data_tree_leaf; -mod public_data_tree_leaf_preimage; - -use abis::kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}; mod recursion; mod data; mod storage; mod validate; + +pub use abis::kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr index 244aadd3bf3..47f3007f449 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr @@ -6,11 +6,11 @@ mod merkle_tree; mod root; mod variable_merkle_tree; -use leaf_preimage::{IndexedTreeLeafPreimage, LeafPreimage}; -use membership::{ +pub use leaf_preimage::{IndexedTreeLeafPreimage, LeafPreimage}; +pub use membership::{ assert_check_membership, assert_check_non_membership, check_membership, conditionally_assert_check_membership, MembershipWitness }; -use merkle_tree::MerkleTree; -use variable_merkle_tree::VariableMerkleTree; -use root::{calculate_empty_tree_root, calculate_subtree_root, root_from_sibling_path}; +pub use merkle_tree::MerkleTree; +pub use variable_merkle_tree::VariableMerkleTree; +pub use root::{calculate_empty_tree_root, calculate_subtree_root, root_from_sibling_path}; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr index ffc3fe1561d..dc0ca51c9d2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr @@ -1,4 +1,4 @@ -use crate::{traits::Empty, hash::accumulate_sha256}; +use crate::{hash::accumulate_sha256}; // N = maximum leaves // For now we only care about the root struct VariableMerkleTree { @@ -33,7 +33,9 @@ impl VariableMerkleTree { // pub fn new_sha(leaves: [Field; N], num_non_empty_leaves: u32) -> Self { // Find size of tree required - let height = get_height(num_non_empty_leaves, 0); + let height = unsafe { + get_height(num_non_empty_leaves, 0) + }; let next_power_2 = 2 << height; let prev_power_2 = next_power_2 / 2; assert( diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/point.nr b/noir-projects/noir-protocol-circuits/crates/types/src/point.nr index 5de5cc7ec03..0a835e19816 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/point.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/point.nr @@ -1,4 +1,4 @@ -use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point; +pub use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point; use crate::{traits::{Empty, Hash, Serialize}, hash::poseidon2_hash}; global POINT_LENGTH: Field = 3; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf.nr b/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf.nr deleted file mode 100644 index 79f21b9734a..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf.nr +++ /dev/null @@ -1,27 +0,0 @@ -use crate::traits::Empty; - -struct PublicDataTreeLeaf { - slot: Field, - value: Field, -} - -impl Eq for PublicDataTreeLeaf { - fn eq(self, other: Self) -> bool { - (self.slot == other.slot) & (self.value == other.value) - } -} - -impl Empty for PublicDataTreeLeaf { - fn empty() -> Self { - Self { - slot: 0, - value: 0, - } - } -} - -impl PublicDataTreeLeaf { - pub fn is_empty(self) -> bool { - (self.slot == 0) & (self.value == 0) - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/scalar.nr b/noir-projects/noir-protocol-circuits/crates/types/src/scalar.nr index a108f4f23bb..d06aa49c6b5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/scalar.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/scalar.nr @@ -1,4 +1,4 @@ -use dep::std::embedded_curve_ops::EmbeddedCurveScalar as Scalar; +pub use dep::std::embedded_curve_ops::EmbeddedCurveScalar as Scalar; use crate::traits::{Empty, Serialize}; global SCALAR_SIZE: Field = 2; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr b/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr index c0a0154d63b..bb8449d8ef5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr @@ -1,7 +1,7 @@ use crate::{ abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH}, constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH}, - partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize}, + partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Serialize}, utils::arr_copy_slice }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index 9a2c9100fa5..970d06352d3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -39,15 +39,14 @@ use crate::{ }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, hash::{ - compute_l2_to_l1_hash, compute_tx_logs_hash, compute_tx_note_logs_hash, compute_siloed_nullifier, - silo_encrypted_log_hash, silo_note_hash, silo_unencrypted_log_hash, mask_encrypted_log_hash + compute_l2_to_l1_hash, compute_tx_logs_hash, compute_siloed_nullifier, silo_note_hash, + silo_unencrypted_log_hash, mask_encrypted_log_hash }, header::Header, merkle_tree::membership::MembershipWitness, messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message}, partial_state_reference::PartialStateReference, tests::fixtures, transaction::{tx_context::TxContext, tx_request::TxRequest}, traits::Empty, - recursion::{verification_key::VerificationKey, proof::{NestedRecursiveProof, RecursiveProof}}, - point::Point + recursion::{verification_key::VerificationKey, proof::NestedRecursiveProof}, point::Point }; fn subarray(arr: [T; N]) -> [T; M] { @@ -727,15 +726,15 @@ impl FixtureBuilder { } pub fn add_public_data_read_request(&mut self, leaf_slot: Field, value: Field) { - self.public_data_reads.push(PublicDataRead { leaf_slot, value }); + self.public_data_reads.push(PublicDataRead { leaf_slot, value, counter: self.next_counter() }); } pub fn append_public_data_read_requests(&mut self, num_reads: u32) { let index_offset = self.public_data_reads.len(); for i in 0..self.public_data_reads.max_len() { if i < num_reads { - let read_request = self.mock_public_data_read(index_offset + i); - self.add_public_data_read_request(read_request.leaf_slot, read_request.value); + let (leaf_slot, value) = self.mock_public_data_read(index_offset + i); + self.add_public_data_read_request(leaf_slot, value); } } } @@ -808,14 +807,6 @@ impl FixtureBuilder { } } - pub fn add_read_request_for_pending_public_data(&mut self, public_date_update_request_index: u32) -> u32 { - let new_read_request_index = self.public_data_reads.len(); - let public_write = self.public_data_update_requests.get(public_date_update_request_index); - let read_request = PublicDataRead { leaf_slot: public_write.leaf_slot, value: public_write.new_value }; - self.public_data_reads.push(read_request); - new_read_request_index - } - pub fn add_request_for_key_validation(&mut self, pk_m: Point, sk_app: Field, sk_app_generator: Field) -> u32 { let new_request_index = self.scoped_key_validation_requests_and_generators.len(); let request = KeyValidationRequest { pk_m, sk_app }; @@ -1048,9 +1039,9 @@ impl FixtureBuilder { KeyValidationRequestAndGenerator { request, sk_app_generator: 3 + value_offset } } - fn mock_public_data_read(self, index: u32) -> PublicDataRead { + fn mock_public_data_read(self, index: u32) -> (Field, Field) { let value_offset = 4545 + self.value_offset + index as Field; - PublicDataRead { leaf_slot: value_offset, value: 1 + value_offset } + (value_offset, value_offset + 1) } fn mock_public_data_write(self, index: u32) -> (Field, Field) { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr index 318ee206c37..f711fdec1db 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr @@ -1,12 +1,13 @@ -use crate::address::{AztecAddress, EthAddress, PublicKeysHash, SaltedInitializationHash, PartialAddress}; -use crate::tests::fixtures; -use crate::contract_class_id::ContractClassId; +use crate::{ + address::{AztecAddress, PublicKeysHash, SaltedInitializationHash, PartialAddress}, + contract_class_id::ContractClassId +}; struct ContractData { address: AztecAddress, artifact_hash: Field, contract_address_salt: Field, - contract_class_id: ContractClassId, + contract_class_id: ContractClassId, private_functions_root: Field, public_bytecode_commitment: Field, public_keys_hash: PublicKeysHash, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr index 01e031f90fa..129deea3194 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr @@ -1,4 +1,5 @@ mod fixture_builder; mod fixtures; mod merkle_tree_utils; +mod types; mod utils; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/types.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/types.nr new file mode 100644 index 00000000000..710d711d9a9 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/types.nr @@ -0,0 +1,80 @@ +use crate::{abis::side_effect::Ordered, traits::Empty}; + +struct TestValue { + value: Field, + counter: u32, +} + +impl Empty for TestValue { + fn empty() -> Self { + TestValue { value: 0, counter: 0 } + } +} + +impl Eq for TestValue { + fn eq(self, other: Self) -> bool { + (self.value == other.value) & (self.counter == other.counter) + } +} + +impl Ordered for TestValue { + fn counter(self) -> u32 { + self.counter + } +} + +struct TestTwoValues { + value_1: Field, + value_2: Field, + counter: u32, +} + +impl Empty for TestTwoValues { + fn empty() -> Self { + TestTwoValues { value_1: 0, value_2: 0, counter: 0 } + } +} + +impl Eq for TestTwoValues { + fn eq(self, other: Self) -> bool { + (self.value_1 == other.value_1) & (self.value_2 == other.value_2) & (self.counter == other.counter) + } +} + +impl Ordered for TestTwoValues { + fn counter(self) -> u32 { + self.counter + } +} + +struct TestCombinedValue { + value: Field, +} + +impl Empty for TestCombinedValue { + fn empty() -> Self { + TestCombinedValue { value: 0 } + } +} + +impl Eq for TestCombinedValue { + fn eq(self, other: Self) -> bool { + (self.value == other.value) + } +} + +pub fn sum_two_values(from: TestTwoValues) -> TestValue { + TestValue { value: from.value_1 + from.value_2, counter: from.counter } +} + +pub fn is_summed_from_two_values(from: TestTwoValues, to: TestValue) -> bool { + ((from.value_1 + from.value_2) == to.value) & (from.counter == to.counter) +} + +pub fn combine_two_values(from: TestTwoValues) -> TestCombinedValue { + TestCombinedValue { value: from.value_1 + from.value_2 } +} + +pub fn is_combined_from_two_values(from: TestTwoValues, to: TestCombinedValue) -> bool { + ((from.value_1 + from.value_2) == to.value) +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr index 9890994c051..ae5861a65fe 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr @@ -1,18 +1,8 @@ -use crate::traits::{Empty, is_empty}; - -fn count_non_empty_elements(array: [T; N]) -> u32 where T: Empty + Eq { - let mut length = 0; - for elem in array { - if !is_empty(elem) { - length += 1; - } - } - length -} +use crate::{traits::{Empty, is_empty}, utils::arrays::validate_array}; pub fn assert_array_eq(array: [T; N], expected: [T; S]) where T: Empty + Eq { - assert_eq(count_non_empty_elements(expected), S, "cannot expect empty element in the result"); - assert_eq(count_non_empty_elements(array), S, "mismatch array lengths"); + assert(expected.all(|elem: T| !is_empty(elem)), "cannot expect empty element in the result"); + assert_eq(validate_array(array), S, "mismatch array lengths"); for i in 0..S { assert_eq(array[i], expected[i], "mismatch array elements"); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr index 45225d1c80e..0501d52f85a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr @@ -1,5 +1,5 @@ use crate::{ - address::AztecAddress, abis::function_data::FunctionData, abis::gas_settings::GasSettings, + address::AztecAddress, abis::function_data::FunctionData, constants::{GENERATOR_INDEX__TX_REQUEST, TX_REQUEST_LENGTH}, hash::poseidon2_hash_with_separator, traits::{Hash, Serialize, Deserialize, Empty}, transaction::tx_context::TxContext, utils::reader::Reader @@ -76,8 +76,7 @@ mod tests { function_selector::FunctionSelector, function_data::FunctionData, gas_settings::GasSettings, gas::Gas, gas_fees::GasFees }, - address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, - transaction::{tx_request::TxRequest, tx_context::TxContext} + address::AztecAddress, transaction::{tx_request::TxRequest, tx_context::TxContext} }; #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr index d2358e05f5a..d5bb0291291 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr @@ -1,38 +1,38 @@ -mod assert_combined_deduped_array; +mod assert_combined_array; mod assert_combined_sorted_transformed_value_array; +mod assert_combined_transformed_array; +mod assert_deduped_array; mod assert_exposed_sorted_transformed_value_array; mod assert_sorted_array; mod assert_sorted_transformed_value_array; mod assert_split_sorted_transformed_value_arrays; mod assert_split_transformed_value_arrays; -mod get_sorted_hints; +mod get_sorted_result; mod get_sorted_tuple; mod sort_by; mod sort_by_counter; // Re-exports. -use assert_combined_deduped_array::{ - assert_combined_deduped_array, dedupe_array::dedupe_array, - get_deduped_hints::{DedupedHints, get_deduped_hints}, - sort_by_position_then_counter::sort_by_position_then_counter -}; -use assert_combined_sorted_transformed_value_array::{ +pub use assert_combined_array::{assert_combined_array, combine_arrays}; +pub use assert_combined_sorted_transformed_value_array::{ assert_combined_sorted_transformed_value_array_asc, get_combined_order_hints::{CombinedOrderHint, get_combined_order_hints_asc} }; -use assert_exposed_sorted_transformed_value_array::{ +pub use assert_combined_transformed_array::{assert_combined_transformed_array, combine_and_transform_arrays}; +pub use assert_exposed_sorted_transformed_value_array::{ assert_exposed_sorted_transformed_value_array, get_order_hints::{get_order_hints_asc, get_order_hints_desc, OrderHint} }; -use assert_sorted_array::assert_sorted_array; -use assert_split_sorted_transformed_value_arrays::{ +pub use assert_deduped_array::{assert_deduped_array, dedupe_array}; +pub use assert_sorted_array::assert_sorted_array; +pub use assert_split_sorted_transformed_value_arrays::{ assert_split_sorted_transformed_value_arrays_asc, assert_split_sorted_transformed_value_arrays_desc, get_split_order_hints::{get_split_order_hints_asc, get_split_order_hints_desc, SplitOrderHints} }; -use assert_sorted_transformed_value_array::{assert_sorted_transformed_value_array, assert_sorted_transformed_value_array_capped_size}; -use assert_split_transformed_value_arrays::assert_split_transformed_value_arrays; -use get_sorted_hints::get_sorted_hints; -use sort_by_counter::{sort_by_counter_asc, sort_by_counter_desc}; +pub use assert_sorted_transformed_value_array::{assert_sorted_transformed_value_array, assert_sorted_transformed_value_array_capped_size}; +pub use assert_split_transformed_value_arrays::assert_split_transformed_value_arrays; +pub use get_sorted_result::{get_sorted_result, SortedResult}; +pub use sort_by_counter::{sort_by_counter_asc, sort_by_counter_desc}; use crate::traits::{Empty, is_empty}; @@ -74,23 +74,12 @@ pub fn validate_array(array: [T; N]) -> u32 where T: Empty + Eq { length } -unconstrained fn count_non_empty_elements(array: [T; N]) -> u32 where T: Empty + Eq { - let mut length = 0; - let mut seen_empty = false; - for elem in array { - if is_empty(elem) { - seen_empty = true; - } else if !seen_empty { - length += 1; - } - } - length -} - // Helper function to count the number of non-empty elements in a validated array. // Important: Only use it for validated arrays: validate_array(array) should be true. pub fn array_length(array: [T; N]) -> u32 where T: Empty + Eq { - let length = count_non_empty_elements(array); + let length = unsafe { + find_index_hint(array, |elem: T| is_empty(elem)) + }; if length != 0 { assert(!is_empty(array[length - 1])); } @@ -130,7 +119,11 @@ pub fn array_merge(array1: [T; N], array2: [T; N]) -> [T; N] wher result } -pub fn check_permutation(original_array: [T; N], permuted_array: [T; N], original_indexes: [u32; N]) where T: Eq + Empty { +pub fn check_permutation( + original_array: [T; N], + permuted_array: [T; N], + original_indexes: [u32; N] +) where T: Eq + Empty { let mut seen_value = [false; N]; for i in 0..N { let index = original_indexes[i]; @@ -207,7 +200,9 @@ fn test_array_length_invalid_arrays() { fn find_index_greater_than_min() { let values = [10, 20, 30, 40]; let min = 22; - let index = find_index_hint(values, |v: Field| min.lt(v)); + let index = unsafe { + find_index_hint(values, |v: Field| min.lt(v)) + }; assert_eq(index, 2); } @@ -215,7 +210,9 @@ fn find_index_greater_than_min() { fn find_index_not_found() { let values = [10, 20, 30, 40]; let min = 100; - let index = find_index_hint(values, |v: Field| min.lt(v)); + let index = unsafe { + find_index_hint(values, |v: Field| min.lt(v)) + }; assert_eq(index, 4); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_array.nr new file mode 100644 index 00000000000..90079131ab6 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_array.nr @@ -0,0 +1,141 @@ +use crate::{ + traits::Empty, + utils::arrays::assert_combined_transformed_array::{assert_combined_transformed_array, combine_and_transform_arrays} +}; + +// original_array(_lt/_gte) must be valid, i.e. validate_array(original_array) == true +// This ensures that combined_array is valid when S can only be empty if and only if T is empty. +pub fn assert_combined_array( + original_array_lt: [T; N], + original_array_gte: [T; N], + combined_array: [T; N] +) where T: Empty + Eq { + assert_combined_transformed_array( + original_array_lt, + original_array_gte, + combined_array, + |from: T, to: T| from == to + ) +} + +unconstrained pub fn combine_arrays( + original_array_lt: [T; N], + original_array_gte: [T; N] +) -> [T; N] where T: Empty + Eq { + combine_and_transform_arrays(original_array_lt, original_array_gte, |from: T| from) +} + +mod tests { + use crate::{ + tests::{types::TestValue, utils::pad_end}, + utils::arrays::assert_combined_array::{assert_combined_array, combine_arrays} + }; + + struct TestBuilder { + original_array_lt: [TestValue; N], + original_array_gte: [TestValue; N], + combined_array: [TestValue; N], + } + + impl TestBuilder<10> { + pub fn new_empty() -> Self { + let original_array_lt = pad_end([], TestValue::empty()); + let original_array_gte = pad_end([], TestValue::empty()); + let combined_array = pad_end([], TestValue::empty()); + TestBuilder { original_array_lt, original_array_gte, combined_array } + } + + pub fn new() -> Self { + let original_array_lt = pad_end( + [ + TestValue { value: 11, counter: 2 }, + TestValue { value: 22, counter: 5 }, + TestValue { value: 33, counter: 3 } + ], + TestValue::empty() + ); + + let original_array_gte = pad_end( + [ + TestValue { value: 44, counter: 1 }, + TestValue { value: 55, counter: 4 } + ], + TestValue::empty() + ); + + let combined_array = pad_end( + [ + TestValue { value: 11, counter: 2 }, + TestValue { value: 22, counter: 5 }, + TestValue { value: 33, counter: 3 }, + TestValue { value: 44, counter: 1 }, + TestValue { value: 55, counter: 4 } + ], + TestValue::empty() + ); + + TestBuilder { original_array_lt, original_array_gte, combined_array } + } + + pub fn execute(self) { + assert_combined_array( + self.original_array_lt, + self.original_array_gte, + self.combined_array + ); + } + + pub fn check_and_execute(self) { + let combined = unsafe { + combine_arrays(self.original_array_lt, self.original_array_gte) + }; + assert_eq(combined, self.combined_array); + + self.execute(); + } + } + + #[test] + fn assert_combined_array_empty_succeeds() { + let builder = TestBuilder::new_empty(); + builder.check_and_execute(); + } + + #[test] + fn assert_combined_array_succeeds() { + let builder = TestBuilder::new(); + builder.check_and_execute(); + } + + #[test(should_fail_with="hinted item in the commbined array does not match")] + fn assert_combined_array_extra_item_fails() { + let mut builder = TestBuilder::new(); + + // Add random value to an empty item. + builder.combined_array[7].value = 123; + + builder.execute(); + } + + #[test(should_fail_with="hinted item in the commbined array does not match")] + fn assert_combined_array_missing_item_fails() { + let mut builder = TestBuilder::new(); + + // Clear the last item. + builder.combined_array[4] = TestValue::empty(); + + builder.execute(); + } + + #[test(should_fail_with="hinted item in the commbined array does not match")] + fn assert_combined_array_unordered_fails() { + let mut builder = TestBuilder::new(); + + // Swap the two items. + let tmp = builder.combined_array[3]; + builder.combined_array[3] = builder.combined_array[1]; + builder.combined_array[1] = tmp; + + builder.execute(); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array.nr deleted file mode 100644 index 366ec585a2f..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array.nr +++ /dev/null @@ -1,218 +0,0 @@ -mod assert_combined_permuted_array; -mod assert_deduped_array; -mod dedupe_array; -mod get_deduped_hints; -mod sort_by_position_then_counter; - -use crate::{ - abis::side_effect::{Positioned, Ordered}, traits::{Empty, is_empty}, - utils::arrays::{ - array_length, - assert_combined_deduped_array::{ - assert_combined_permuted_array::assert_combined_permuted_array, - assert_deduped_array::assert_deduped_array, get_deduped_hints::DedupedHints -} -} -}; - -// original_array_(lt/gte) must be valid, i.e. validate_array(original_array) == true -// All non-empty items in the original arrays must be unique, otherwise duplicate values could be merged and -// assert_combined_permuted_array would still pass undetected. -// This is currently used for deduplicating public data writes, where each public data write is unique due to having a unique counter. -pub fn assert_combined_deduped_array( - original_array_lt: [T; N], - original_array_gte: [T; N], - sorted_array: [T; N], - deduped_array: [T; N], - hints: DedupedHints -) where T: Positioned + Ordered + Empty + Eq { - assert_combined_permuted_array( - original_array_lt, - original_array_gte, - sorted_array, - hints.combined_indexes - ); - assert_deduped_array(sorted_array, deduped_array, hints.run_lengths); -} - -mod tests { - use crate::{ - abis::side_effect::{Positioned, Ordered}, tests::utils::pad_end, - utils::arrays::{ - array_merge, - assert_combined_deduped_array::{ - assert_deduped_array::{assert_deduped_array, tests::TestContainer}, - assert_combined_deduped_array, dedupe_array::dedupe_array, - get_deduped_hints::{DedupedHints, get_deduped_hints} - } - } - }; - - fn verify_all( - original_array_lt: [TestContainer; N], - original_array_gte: [TestContainer; N], - sorted_array: [TestContainer; N], - deduped_array: [TestContainer; N], - hints: DedupedHints - ) { - let merged = array_merge(original_array_lt, original_array_gte); - assert_eq(deduped_array, dedupe_array(merged)); - assert_eq(hints, get_deduped_hints(original_array_lt, original_array_gte)); - assert_combined_deduped_array( - original_array_lt, - original_array_gte, - sorted_array, - deduped_array, - hints - ); - } - - #[test] - fn assert_combined_deduped_array_full() { - let original_array_lt = pad_end( - [ - TestContainer { value: 4, position: 3, counter: 2 }, - TestContainer { value: 7, position: 4, counter: 8 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 9, position: 5, counter: 7 } - ], - TestContainer::empty() - ); - let original_array_gte = pad_end( - [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 5, position: 3, counter: 5 }, - TestContainer { value: 6, position: 3, counter: 6 }, - TestContainer { value: 8, position: 4, counter: 9 }, - TestContainer { value: 2, position: 1, counter: 4 } - ], - TestContainer::empty() - ); - let sorted_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 1, counter: 4 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 4, position: 3, counter: 2 }, - TestContainer { value: 5, position: 3, counter: 5 }, - TestContainer { value: 6, position: 3, counter: 6 }, - TestContainer { value: 7, position: 4, counter: 8 }, - TestContainer { value: 8, position: 4, counter: 9 }, - TestContainer { value: 9, position: 5, counter: 7 } - ]; - let deduped_array = [ - TestContainer { value: 2, position: 1, counter: 4 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 6, position: 3, counter: 6 }, - TestContainer { value: 8, position: 4, counter: 9 }, - TestContainer { value: 9, position: 5, counter: 7 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 } - ]; - let hints = DedupedHints { combined_indexes: [3, 6, 2, 8, 0, 4, 5, 7, 1], run_lengths: [2, 1, 3, 2, 1, 0, 0, 0, 0] }; - verify_all( - original_array_lt, - original_array_gte, - sorted_array, - deduped_array, - hints - ); - } - - #[test] - fn assert_combined_deduped_array_padded_empty() { - let original_array_lt = pad_end( - [ - TestContainer { value: 4, position: 3, counter: 2 }, - TestContainer { value: 7, position: 4, counter: 8 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 9, position: 5, counter: 7 } - ], - TestContainer::empty() - ); - let original_array_gte = pad_end( - [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 5, position: 3, counter: 5 }, - TestContainer { value: 6, position: 3, counter: 6 }, - TestContainer { value: 8, position: 4, counter: 9 }, - TestContainer { value: 2, position: 1, counter: 4 } - ], - TestContainer::empty() - ); - let sorted_array = pad_end( - [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 1, counter: 4 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 4, position: 3, counter: 2 }, - TestContainer { value: 5, position: 3, counter: 5 }, - TestContainer { value: 6, position: 3, counter: 6 }, - TestContainer { value: 7, position: 4, counter: 8 }, - TestContainer { value: 8, position: 4, counter: 9 }, - TestContainer { value: 9, position: 5, counter: 7 } - ], - TestContainer::empty() - ); - let deduped_array = pad_end( - [ - TestContainer { value: 2, position: 1, counter: 4 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 6, position: 3, counter: 6 }, - TestContainer { value: 8, position: 4, counter: 9 }, - TestContainer { value: 9, position: 5, counter: 7 } - ], - TestContainer::empty() - ); - let hints = DedupedHints { - combined_indexes: [3, 6, 2, 8, 0, 4, 5, 7, 1, 11, 10, 9], - run_lengths: [2, 1, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0] - }; - verify_all( - original_array_lt, - original_array_gte, - sorted_array, - deduped_array, - hints - ); - } - - #[test] - fn assert_combined_deduped_array_no_duplicates() { - let original_array_lt = pad_end( - [ - TestContainer { value: 3, position: 3, counter: 3 }, - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 2, counter: 2 } - ], - TestContainer::empty() - ); - let original_array_gte = pad_end( - [ - TestContainer { value: 4, position: 4, counter: 4 }, - TestContainer { value: 5, position: 5, counter: 5 } - ], - TestContainer::empty() - ); - let sorted_array = pad_end( - [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 2, counter: 2 }, - TestContainer { value: 3, position: 3, counter: 3 }, - TestContainer { value: 4, position: 4, counter: 4 }, - TestContainer { value: 5, position: 5, counter: 5 } - ], - TestContainer::empty() - ); - let deduped_array = sorted_array; - let hints = DedupedHints { combined_indexes: [2, 0, 1, 3, 4, 7, 6, 5], run_lengths: [1, 1, 1, 1, 1, 0, 0, 0] }; - verify_all( - original_array_lt, - original_array_gte, - sorted_array, - deduped_array, - hints - ); - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/assert_combined_permuted_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/assert_combined_permuted_array.nr deleted file mode 100644 index 2b4786b1e07..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/assert_combined_permuted_array.nr +++ /dev/null @@ -1,135 +0,0 @@ -use crate::{traits::{Empty, is_empty}, utils::arrays::array_length}; - -pub fn assert_combined_permuted_array( - original_array_lt: [T; N], - original_array_gte: [T; N], - permuted_array: [T; N], - combined_indexes: [u32; N] -) where T: Empty + Eq { - let num_lt = array_length(original_array_lt); - let num_gte = array_length(original_array_gte); - let total_num = num_lt + num_gte; - - let mut is_lt = true; - let mut should_be_empty = false; - for i in 0..N { - is_lt &= i != num_lt; - should_be_empty |= i == total_num; - - let from = if is_lt { - original_array_lt[i] - } else { - original_array_gte[i - num_lt] - }; - - let combined_index = combined_indexes[i]; - let to = permuted_array[combined_index]; - assert_eq(from, to, "hinted item in the permuted array does not match"); - - if should_be_empty { - assert(is_empty(permuted_array[i]), "permuted array must be padded with empty items"); - } - } -} - -mod tests { - use crate::utils::arrays::assert_combined_deduped_array::assert_combined_permuted_array::assert_combined_permuted_array; - - struct TestBuilder { - original_array_lt: [Field; N], - original_array_gte: [Field; N], - permuted_array: [Field; N], - combined_indexes: [u32; N] - } - - impl TestBuilder<7> { - pub fn new() -> Self { - let original_array_lt = [6, 3, 8, 1, 0, 0, 0]; - let original_array_gte = [4, 9, 5, 0, 0, 0, 0]; - let permuted_array = [5, 8, 9, 3, 1, 6, 4]; - let combined_indexes = [5, 3, 1, 4, 6, 2, 0]; - TestBuilder { original_array_lt, original_array_gte, permuted_array, combined_indexes } - } - } - - impl TestBuilder<10> { - pub fn new_with_padded_zeros() -> Self { - let original_array_lt = [6, 3, 8, 1, 0, 0, 0, 0, 0, 0]; - let original_array_gte = [4, 9, 5, 0, 0, 0, 0, 0, 0, 0]; - let permuted_array = [5, 8, 9, 3, 1, 6, 4, 0, 0, 0]; - let combined_indexes = [5, 3, 1, 4, 6, 2, 0, 7, 8, 9]; - TestBuilder { original_array_lt, original_array_gte, permuted_array, combined_indexes } - } - } - - impl TestBuilder { - pub fn verify(self) { - assert_combined_permuted_array( - self.original_array_lt, - self.original_array_gte, - self.permuted_array, - self.combined_indexes - ); - } - } - - #[test] - fn assert_combined_permuted_array_full() { - let builder = TestBuilder::new(); - builder.verify() - } - - #[test] - fn assert_combined_permuted_array_padded_empty() { - let builder = TestBuilder::new_with_padded_zeros(); - builder.verify() - } - - #[test(should_fail_with="hinted item in the permuted array does not match")] - fn assert_combined_permuted_array_missing_value_fails() { - let mut builder = TestBuilder::new_with_padded_zeros(); - - // Clear a value. - builder.permuted_array[6] = 0; - - builder.verify() - } - - #[test(should_fail_with="hinted item in the permuted array does not match")] - fn assert_combined_permuted_array_duplicated_item_fails() { - let mut builder = TestBuilder::new_with_padded_zeros(); - - // Duplicate a value. - builder.permuted_array[3] = builder.permuted_array[2]; - - builder.verify() - } - - #[test(should_fail_with="permuted array must be padded with empty items")] - fn assert_combined_permuted_array_extra_item_fails() { - let mut builder = TestBuilder::new_with_padded_zeros(); - - // Overwrite the first empty value with a non-empty value. - builder.permuted_array[8] = builder.permuted_array[1]; - // Update the index to point to an empty value. - builder.combined_indexes[8] = 9; - - builder.verify() - } - - #[test(should_fail_with="permuted array must be padded with empty items")] - fn assert_combined_permuted_array_mixed_empty_item_fails() { - let mut builder = TestBuilder::new_with_padded_zeros(); - - // Swap the positions of a non-empty item and an empty item. - builder.permuted_array[8] = builder.permuted_array[4]; - builder.permuted_array[4] = 0; - // Update the index to point to the value. - let original_index = 3; - assert_eq(builder.original_array_lt[original_index], builder.permuted_array[8]); - builder.combined_indexes[original_index] = 8; - builder.combined_indexes[8] = 4; - - builder.verify() - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/assert_deduped_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/assert_deduped_array.nr deleted file mode 100644 index c0fb2c0ea77..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/assert_deduped_array.nr +++ /dev/null @@ -1,343 +0,0 @@ -use crate::{abis::side_effect::{Positioned, Ordered}, traits::Empty, utils::arrays::{array_length, validate_array}}; - -/* - The sorted_array here needs to be sorted based on the `position` field of the container, - *and* a secondary sort based on the `counter` field of the container. - - For example, the storage slot in the case of public data update requests. - The run_lengths array should contain the length of each run of the sorted_array. - The deduped_array should contain the deduplicated array. - - For example, if the original array is writing `(position,value,counter)`s: - [ (1,1,1), (1,2,4), (2,3,3), (3,4,2), (3,5,5), (3,6,6), (4,7,8), (4,8,9), (5,9,7), (0,0,0), ... padding with zeros ] - then run_lengths array is: - [ - 2, // run of 1s - 1, // run of 2 - 3, // run of 3s - 2, // run of 4s - 1, // run of 5 - 0, - 0, - ... padding with zeros - ] - - then the deduped_array should be: - [ (1,2,4), (2,3,3), (3,6,6), (4,8,9), (5,9,7), (0,0,0), ... padding with zeros ] -*/ -pub fn assert_deduped_array( - sorted_array: [T; N], - deduped_array: [T; N], - run_lengths: [u32; N] -) where T: Positioned + Ordered + Empty + Eq { - let num_non_empty_items = array_length(sorted_array); - let deduped_len = validate_array(deduped_array); // This makes sure that the array is padded with empty items. - - // container at the start of the current run - let mut start_run_container = sorted_array[0]; - // the index we are collapsing into - let mut deduped_index = 0; - // the length of the current run we are collapsing - let mut run_counter = 0; - let mut should_check = true; - for i in 0..N { - should_check &= i != num_non_empty_items; - if should_check { - let current_container = sorted_array[i]; - - if run_counter == 0 { - // Start a new run. - run_counter = run_lengths[deduped_index]; - if i != 0 { - assert( - start_run_container.position().lt(current_container.position()), "Containers in a run must be sorted by position" - ); - } - start_run_container = current_container; - } - - assert(run_counter != 0, "Invalid run length"); - run_counter -= 1; - - assert_eq( - current_container.position(), start_run_container.position(), "The position of the current container must match the start of the run" - ); - - if run_counter == 0 { - // End of the run. - assert_eq( - deduped_array[deduped_index], current_container, "The container we are collapsing into must match the current container" - ); - deduped_index += 1; - } else { - // We're in a run, so this container must have a lower counter. - // Note we don't check for overflow here, as the run_lengths array must be correct. - assert( - current_container.counter() < sorted_array[i + 1].counter(), "Containers in a run must be sorted by counter" - ); - } - } - } - - assert_eq(deduped_index, deduped_len, "Final deduped index does not match deduped array length"); -} - -mod tests { - use crate::{ - abis::side_effect::{Positioned, Ordered}, traits::Empty, tests::utils::pad_end, - utils::arrays::assert_combined_deduped_array::{assert_deduped_array::assert_deduped_array} - }; - - struct TestContainer { - value: Field, - position: Field, - counter: u32, - } - - impl Positioned for TestContainer { - fn position(self) -> Field { - self.position - } - } - - impl Ordered for TestContainer { - fn counter(self) -> u32 { - self.counter - } - } - - impl Empty for TestContainer { - fn empty() -> Self { - TestContainer { value: 0, position: 0, counter: 0 } - } - } - - impl Eq for TestContainer { - fn eq(self, other: Self) -> bool { - self.value.eq(other.value) & self.position.eq(other.position) & self.counter.eq(other.counter) - } - } - - #[test] - fn assert_deduped_array_basic_test() { - let sorted_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 1, counter: 4 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 4, position: 3, counter: 2 }, - TestContainer { value: 5, position: 3, counter: 5 }, - TestContainer { value: 6, position: 3, counter: 6 }, - TestContainer { value: 7, position: 4, counter: 8 }, - TestContainer { value: 8, position: 4, counter: 9 }, - TestContainer { value: 9, position: 5, counter: 7 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 } - ]; - let deduped_array = [ - TestContainer { value: 2, position: 1, counter: 4 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 6, position: 3, counter: 6 }, - TestContainer { value: 8, position: 4, counter: 9 }, - TestContainer { value: 9, position: 5, counter: 7 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 } - ]; - let run_lengths = [2, 1, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } - - #[test] - fn assert_deduped_array_empty_arrays() { - let sorted_array = [TestContainer::empty(); 12]; - let deduped_array = [TestContainer::empty(); 12]; - let run_lengths = [0; 12]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } - - #[test] - fn assert_deduped_array_no_duplicates() { - let sorted_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 2, counter: 2 }, - TestContainer { value: 3, position: 3, counter: 3 }, - TestContainer { value: 4, position: 4, counter: 4 }, - TestContainer { value: 5, position: 5, counter: 5 } - ]; - let deduped_array = sorted_array; - let run_lengths = [1; 5]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } - - #[test] - fn assert_deduped_array_no_duplicates_padded_empty() { - let sorted_array = pad_end( - [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 2, counter: 2 }, - TestContainer { value: 3, position: 3, counter: 3 }, - TestContainer { value: 4, position: 4, counter: 4 }, - TestContainer { value: 5, position: 5, counter: 5 } - ], - TestContainer::empty() - ); - let deduped_array = sorted_array; - let run_lengths = [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } - - #[test] - fn assert_deduped_array_single_run_at_end() { - let sorted_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 2, counter: 2 }, - TestContainer { value: 3, position: 3, counter: 3 }, - TestContainer { value: 4, position: 4, counter: 4 }, - TestContainer { value: 5, position: 5, counter: 5 }, - TestContainer { value: 6, position: 6, counter: 7 }, - TestContainer { value: 7, position: 6, counter: 8 }, - TestContainer { value: 8, position: 6, counter: 9 } - ]; - let deduped_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 2, counter: 2 }, - TestContainer { value: 3, position: 3, counter: 3 }, - TestContainer { value: 4, position: 4, counter: 4 }, - TestContainer { value: 5, position: 5, counter: 5 }, - TestContainer { value: 8, position: 6, counter: 9 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 } - ]; - let run_lengths = [1, 1, 1, 1, 1, 3, 0, 0]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } - - #[test] - fn assert_deduped_array_all_duplicates() { - let sorted_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 1, counter: 2 }, - TestContainer { value: 3, position: 1, counter: 3 }, - TestContainer { value: 4, position: 1, counter: 4 }, - TestContainer { value: 5, position: 1, counter: 5 }, - TestContainer { value: 6, position: 1, counter: 6 }, - TestContainer { value: 7, position: 1, counter: 7 }, - TestContainer { value: 8, position: 1, counter: 8 }, - TestContainer { value: 9, position: 1, counter: 9 } - ]; - let deduped_array = pad_end( - [TestContainer { value: 9, position: 1, counter: 9 }], - TestContainer::empty() - ); - let run_lengths = [9, 0, 0, 0, 0, 0, 0, 0, 0]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } - - #[test(should_fail_with="The position of the current container must match the start of the run")] - fn assert_deduped_array_mismatched_position_in_run() { - let sorted_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 1, counter: 2 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 4, position: 3, counter: 4 } - ]; - let deduped_array = [ - TestContainer { value: 2, position: 1, counter: 2 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 4, position: 3, counter: 4 }, - TestContainer { value: 0, position: 0, counter: 0 } - ]; - let run_lengths = [3, 1, 1, 0]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } - - #[test(should_fail_with="The container we are collapsing into must match the current container")] - fn assert_deduped_array_mismatched_deduped_value() { - let sorted_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 1, counter: 2 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 4, position: 3, counter: 4 } - ]; - let deduped_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 4, position: 3, counter: 4 }, - TestContainer { value: 0, position: 0, counter: 0 } - ]; - let run_lengths = [2, 1, 1, 0]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } - - #[test(should_fail_with="Containers in a run must be sorted by position")] - fn assert_deduped_array_missed_deduped_value() { - let sorted_array = [ - TestContainer { value: 1, position: 1, counter: 1 },// This should've been deduped. - TestContainer { value: 2, position: 1, counter: 2 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 4, position: 3, counter: 4 } - ]; - let deduped_array = sorted_array; - let run_lengths = [1, 1, 1, 1]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } - - #[test(should_fail_with="Containers in a run must be sorted by position")] - fn assert_deduped_array_unsorted_array() { - let sorted_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 2, position: 1, counter: 2 },// Not sorted by position. - TestContainer { value: 4, position: 3, counter: 4 } - ]; - let deduped_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 2, position: 1, counter: 2 }, - TestContainer { value: 4, position: 3, counter: 4 } - ]; - let run_lengths = [1, 1, 1, 1]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } - - #[test(should_fail_with="Final deduped index does not match deduped array length")] - fn assert_deduped_array_extra_value() { - let sorted_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 1, counter: 2 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 4, position: 3, counter: 4 } - ]; - let deduped_array = [ - TestContainer { value: 2, position: 1, counter: 2 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer { value: 4, position: 3, counter: 4 }, - TestContainer { value: 1, position: 1, counter: 1 }// This should be empty. - ]; - let run_lengths = [2, 1, 1, 0]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } - - #[test(should_fail_with="invalid array")] - fn assert_deduped_array_padded_non_empty_value() { - let sorted_array = [ - TestContainer { value: 1, position: 1, counter: 1 }, - TestContainer { value: 2, position: 1, counter: 2 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer::empty() - ]; - let deduped_array = [ - TestContainer { value: 2, position: 1, counter: 2 }, - TestContainer { value: 3, position: 2, counter: 3 }, - TestContainer::empty(), - TestContainer { value: 1, position: 1, counter: 1 }// This should be empty. - ]; - let run_lengths = [2, 1, 0, 0]; - assert_deduped_array(sorted_array, deduped_array, run_lengths); - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/dedupe_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/dedupe_array.nr deleted file mode 100644 index 3aa86e380c8..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/dedupe_array.nr +++ /dev/null @@ -1,131 +0,0 @@ -use crate::{ - abis::side_effect::{Ordered, Positioned}, traits::Empty, - utils::arrays::assert_combined_deduped_array::sort_by_position_then_counter::sort_by_position_then_counter -}; - -pub fn dedupe_array(array: [T; N]) -> [T; N] where T: Positioned + Ordered + Empty + Eq { - let sorted = sort_by_position_then_counter(array); - let mut deduped = [T::empty(); N]; - let mut num_deduped = 0; - let mut prev_position = sorted[0].position(); - for item in sorted { - let position = item.position(); - if position != prev_position { - num_deduped += 1; - } - deduped[num_deduped] = item; - prev_position = position; - } - deduped -} - -mod tests { - use crate::{ - tests::utils::pad_end, - utils::arrays::assert_combined_deduped_array::{assert_deduped_array::tests::TestContainer, dedupe_array::dedupe_array} - }; - - #[test] - fn dedupe_array_padded_empty() { - let original_array = [ - TestContainer { value: 11, position: 3, counter: 2 }, - TestContainer { value: 55, position: 4, counter: 9 }, - TestContainer { value: 99, position: 3, counter: 5 }, - TestContainer { value: 66, position: 1, counter: 1 }, - TestContainer { value: 44, position: 4, counter: 8 }, - TestContainer { value: 77, position: 5, counter: 7 }, - TestContainer { value: 33, position: 1, counter: 4 }, - TestContainer { value: 22, position: 3, counter: 6 }, - TestContainer { value: 88, position: 2, counter: 3 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 } - ]; - let deduped_array = [ - TestContainer { value: 33, position: 1, counter: 4 }, - TestContainer { value: 88, position: 2, counter: 3 }, - TestContainer { value: 22, position: 3, counter: 6 }, - TestContainer { value: 55, position: 4, counter: 9 }, - TestContainer { value: 77, position: 5, counter: 7 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 } - ]; - assert_eq(dedupe_array(original_array), deduped_array); - } - - #[test] - fn dedupe_array_empty_arrays() { - let original_array = [TestContainer::empty(); 12]; - let deduped_array = [TestContainer::empty(); 12]; - assert_eq(dedupe_array(original_array), deduped_array); - } - - #[test] - fn dedupe_array_no_duplicates() { - let original_array = [ - TestContainer { value: 88, position: 3, counter: 3 }, - TestContainer { value: 11, position: 4, counter: 4 }, - TestContainer { value: 33, position: 2, counter: 2 }, - TestContainer { value: 99, position: 5, counter: 5 }, - TestContainer { value: 66, position: 1, counter: 1 } - ]; - let deduped_array = [ - TestContainer { value: 66, position: 1, counter: 1 }, - TestContainer { value: 33, position: 2, counter: 2 }, - TestContainer { value: 88, position: 3, counter: 3 }, - TestContainer { value: 11, position: 4, counter: 4 }, - TestContainer { value: 99, position: 5, counter: 5 } - ]; - assert_eq(dedupe_array(original_array), deduped_array); - } - - #[test] - fn dedupe_array_no_duplicates_padded_empty() { - let original_array = [ - TestContainer { value: 88, position: 3, counter: 3 }, - TestContainer { value: 11, position: 4, counter: 4 }, - TestContainer { value: 33, position: 2, counter: 2 }, - TestContainer { value: 99, position: 5, counter: 5 }, - TestContainer { value: 66, position: 1, counter: 1 }, - TestContainer::empty(), - TestContainer::empty(), - TestContainer::empty() - ]; - let deduped_array = [ - TestContainer { value: 66, position: 1, counter: 1 }, - TestContainer { value: 33, position: 2, counter: 2 }, - TestContainer { value: 88, position: 3, counter: 3 }, - TestContainer { value: 11, position: 4, counter: 4 }, - TestContainer { value: 99, position: 5, counter: 5 }, - TestContainer::empty(), - TestContainer::empty(), - TestContainer::empty() - ]; - assert_eq(dedupe_array(original_array), deduped_array); - } - - #[test] - fn dedupe_array_all_duplicates() { - let original_array = [ - TestContainer { value: 55, position: 1, counter: 8 }, - TestContainer { value: 33, position: 1, counter: 2 }, - TestContainer { value: 11, position: 1, counter: 4 }, - TestContainer { value: 88, position: 1, counter: 3 }, - TestContainer { value: 99, position: 1, counter: 5 }, - TestContainer { value: 77, position: 1, counter: 9 }, - TestContainer { value: 66, position: 1, counter: 1 }, - TestContainer { value: 44, position: 1, counter: 7 }, - TestContainer { value: 22, position: 1, counter: 6 } - ]; - let deduped_array = pad_end( - [TestContainer { value: 77, position: 1, counter: 9 }], - TestContainer::empty() - ); - assert_eq(dedupe_array(original_array), deduped_array); - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/get_deduped_hints.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/get_deduped_hints.nr deleted file mode 100644 index 2f88b95392e..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/get_deduped_hints.nr +++ /dev/null @@ -1,49 +0,0 @@ -use crate::{ - abis::side_effect::{Ordered, Positioned}, traits::Empty, - utils::arrays::{ - array_merge, - assert_combined_deduped_array::sort_by_position_then_counter::compare_by_position_then_counter, - get_sorted_tuple::get_sorted_tuple -} -}; - -struct DedupedHints { - combined_indexes: [u32; N], - run_lengths: [u32; N], -} - -impl Eq for DedupedHints { - fn eq(self, other: Self) -> bool { - (self.combined_indexes == other.combined_indexes) & (self.run_lengths == other.run_lengths) - } -} - -pub fn get_deduped_hints( - original_array_lt: [T; N], - original_array_gte: [T; N] -) -> DedupedHints where T: Positioned + Ordered + Empty + Eq { - let mut combined_indexes = [0; N]; - let mut run_lengths = BoundedVec::new(); - - let merged = array_merge(original_array_lt, original_array_gte); - let sorted = get_sorted_tuple(merged, compare_by_position_then_counter); - let mut prev_position = sorted[0].elem.position(); - let mut run_length = 0; - for i in 0..sorted.len() { - combined_indexes[sorted[i].original_index] = i; - - let position = sorted[i].elem.position(); - if position != 0 { - if position != prev_position { - run_lengths.push(run_length); - run_length = 1; - } else { - run_length += 1; - } - prev_position = position; - } - } - run_lengths.push(run_length); - - DedupedHints { combined_indexes, run_lengths: run_lengths.storage } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/sort_by_position_then_counter.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/sort_by_position_then_counter.nr deleted file mode 100644 index b017e68ec0f..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_deduped_array/sort_by_position_then_counter.nr +++ /dev/null @@ -1,53 +0,0 @@ -use crate::{abis::side_effect::{Positioned, Ordered}}; - -pub fn compare_by_position_then_counter(a: T, b: T) -> bool where T: Positioned + Ordered { - if a.position() == b.position() { - (a.counter() == 0) | (b.counter() > a.counter()) - } else { - (b.position() == 0) | ((a.position() != 0) & a.position().lt(b.position())) - } -} - -pub fn sort_by_position_then_counter(array: [T; N]) -> [T; N] where T: Positioned + Ordered { - array.sort_via(|a, b| compare_by_position_then_counter(a, b)) -} - -mod tests { - use crate::utils::arrays::assert_combined_deduped_array::{ - assert_deduped_array::tests::TestContainer, - sort_by_position_then_counter::sort_by_position_then_counter - }; - - #[test] - fn sort_by_position_then_counter_empty_padded() { - let original_array = [ - TestContainer { value: 55, position: 4, counter: 8 }, - TestContainer { value: 11, position: 3, counter: 5 }, - TestContainer { value: 88, position: 1, counter: 4 }, - TestContainer { value: 44, position: 3, counter: 2 }, - TestContainer { value: 33, position: 1, counter: 1 }, - TestContainer { value: 66, position: 5, counter: 7 }, - TestContainer { value: 99, position: 4, counter: 9 }, - TestContainer { value: 77, position: 2, counter: 3 }, - TestContainer { value: 22, position: 3, counter: 6 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 } - ]; - let expected = [ - TestContainer { value: 33, position: 1, counter: 1 }, - TestContainer { value: 88, position: 1, counter: 4 }, - TestContainer { value: 77, position: 2, counter: 3 }, - TestContainer { value: 44, position: 3, counter: 2 }, - TestContainer { value: 11, position: 3, counter: 5 }, - TestContainer { value: 22, position: 3, counter: 6 }, - TestContainer { value: 55, position: 4, counter: 8 }, - TestContainer { value: 99, position: 4, counter: 9 }, - TestContainer { value: 66, position: 5, counter: 7 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 }, - TestContainer { value: 0, position: 0, counter: 0 } - ]; - assert_eq(sort_by_position_then_counter(original_array), expected); - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array.nr index 6eb7869fb59..89d8c9c3094 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array.nr @@ -9,7 +9,9 @@ use crate::{ }; fn get_num_private_items(array: [T; N]) -> u32 where T: Ordered + Empty + Eq { - let length = count_private_items(array); + let length = unsafe { + count_private_items(array) + }; if length != 0 { let last_private_item = array[length - 1]; assert(!is_empty(last_private_item) & (last_private_item.counter() == 0)); @@ -83,7 +85,8 @@ pub fn assert_combined_sorted_transformed_value_array_asc mod tests { use crate::{ - abis::side_effect::Ordered, tests::utils::pad_end, traits::Empty, + tests::utils::pad_end, + tests::types::{combine_two_values, is_combined_from_two_values, TestCombinedValue, TestTwoValues}, utils::arrays::{ array_merge, assert_combined_sorted_transformed_value_array::{ @@ -94,99 +97,49 @@ mod tests { } }; - struct TestItem { - name: Field, - price: Field, - tax: Field, - counter: u32, - } - - impl Ordered for TestItem { - fn counter(self) -> u32 { - self.counter - } - } - - impl Empty for TestItem { - fn empty() -> Self { - TestItem { name: 0, price: 0, tax: 0, counter: 0 } - } - } - - impl Eq for TestItem { - fn eq(self, other: Self) -> bool { - (self.name == other.name) & (self.price == other.price) & (self.tax == other.tax) & (self.counter == other.counter) - } - } - - struct TestValue { - name: Field, - total: Field, - } - - impl Empty for TestValue { - fn empty() -> Self { - TestValue { name: 0, total: 0 } - } - } - - impl Eq for TestValue { - fn eq(self, other: Self) -> bool { - (self.name == other.name) & (self.total == other.total) - } - } - - fn transform(item: TestItem) -> TestValue { - TestValue { name: item.name, total: item.price + item.tax } - } - - fn is_transformed(item: TestItem, value: TestValue) -> bool { - (item.name == value.name) & ((item.price + item.tax) == value.total) - } - - struct TestDataBuilder { - original_array_lt: [T; N], - original_array_gte: [T; N], - sorted_transformed_value_array: [S; N], + struct TestDataBuilder { + original_array_lt: [TestTwoValues; N], + original_array_gte: [TestTwoValues; N], + sorted_transformed_value_array: [TestCombinedValue; N], hints: [CombinedOrderHint; N], } - impl TestDataBuilder { + impl TestDataBuilder<12> { pub fn new() -> Self { let original_array_lt = pad_end( [ - TestItem { name: 7, price: 40, tax: 7, counter: 0 }, - TestItem { name: 4, price: 70, tax: 6, counter: 0 }, - TestItem { name: 6, price: 80, tax: 1, counter: 22 }, - TestItem { name: 3, price: 30, tax: 4, counter: 11 } + TestTwoValues { value_1: 40, value_2: 7, counter: 0 }, + TestTwoValues { value_1: 70, value_2: 6, counter: 0 }, + TestTwoValues { value_1: 80, value_2: 1, counter: 22 }, + TestTwoValues { value_1: 30, value_2: 4, counter: 11 } ], - TestItem::empty() + TestTwoValues::empty() ); let original_array_gte = pad_end( [ - TestItem { name: 9, price: 20, tax: 2, counter: 0 }, - TestItem { name: 8, price: 90, tax: 3, counter: 0 }, - TestItem { name: 5, price: 50, tax: 9, counter: 55 }, - TestItem { name: 1, price: 60, tax: 8, counter: 33 }, - TestItem { name: 2, price: 10, tax: 5, counter: 44 } + TestTwoValues { value_1: 20, value_2: 2, counter: 0 }, + TestTwoValues { value_1: 90, value_2: 3, counter: 0 }, + TestTwoValues { value_1: 50, value_2: 9, counter: 55 }, + TestTwoValues { value_1: 60, value_2: 8, counter: 33 }, + TestTwoValues { value_1: 10, value_2: 5, counter: 44 } ], - TestItem::empty() + TestTwoValues::empty() ); let sorted_transformed_value_array = pad_end( [ - TestValue { name: 7, total: 47 }, - TestValue { name: 4, total: 76 }, - TestValue { name: 9, total: 22 }, - TestValue { name: 8, total: 93 }, - TestValue { name: 3, total: 34 }, - TestValue { name: 6, total: 81 }, - TestValue { name: 1, total: 68 }, - TestValue { name: 2, total: 15 }, - TestValue { name: 5, total: 59 } + TestCombinedValue { value: 47 }, + TestCombinedValue { value: 76 }, + TestCombinedValue { value: 22 }, + TestCombinedValue { value: 93 }, + TestCombinedValue { value: 34 }, + TestCombinedValue { value: 81 }, + TestCombinedValue { value: 68 }, + TestCombinedValue { value: 15 }, + TestCombinedValue { value: 59 } ], - TestValue::empty() + TestCombinedValue::empty() ); let hints = [ @@ -208,34 +161,34 @@ mod tests { } } - impl TestDataBuilder { + impl TestDataBuilder<8> { pub fn new_without_prepended() -> Self { let original_array_lt = pad_end( [ - TestItem { name: 6, price: 80, tax: 1, counter: 22 }, - TestItem { name: 3, price: 30, tax: 4, counter: 11 } + TestTwoValues { value_1: 80, value_2: 1, counter: 22 }, + TestTwoValues { value_1: 30, value_2: 4, counter: 11 } ], - TestItem::empty() + TestTwoValues::empty() ); let original_array_gte = pad_end( [ - TestItem { name: 5, price: 50, tax: 9, counter: 55 }, - TestItem { name: 1, price: 60, tax: 8, counter: 33 }, - TestItem { name: 2, price: 10, tax: 5, counter: 44 } + TestTwoValues { value_1: 50, value_2: 9, counter: 55 }, + TestTwoValues { value_1: 60, value_2: 8, counter: 33 }, + TestTwoValues { value_1: 10, value_2: 5, counter: 44 } ], - TestItem::empty() + TestTwoValues::empty() ); let sorted_transformed_value_array = pad_end( [ - TestValue { name: 3, total: 34 }, - TestValue { name: 6, total: 81 }, - TestValue { name: 1, total: 68 }, - TestValue { name: 2, total: 15 }, - TestValue { name: 5, total: 59 } + TestCombinedValue { value: 34 }, + TestCombinedValue { value: 81 }, + TestCombinedValue { value: 68 }, + TestCombinedValue { value: 15 }, + TestCombinedValue { value: 59 } ], - TestValue::empty() + TestCombinedValue::empty() ); let hints = [ @@ -253,7 +206,7 @@ mod tests { } } - impl TestDataBuilder { + impl TestDataBuilder { pub fn swap_items(&mut self, from: u32, to: u32) { let tmp = self.sorted_transformed_value_array[from]; self.sorted_transformed_value_array[from] = self.sorted_transformed_value_array[to]; @@ -271,36 +224,36 @@ mod tests { self.original_array_lt, self.original_array_gte, self.sorted_transformed_value_array, - is_transformed, + is_combined_from_two_values, self.hints ); } + + pub fn check_and_execute(self) { + let hints = unsafe { + get_combined_order_hints_asc(self.original_array_lt, self.original_array_gte) + }; + assert_eq(hints, self.hints); + + let sorted = unsafe { + sort_by_counter_asc(array_merge(self.original_array_lt, self.original_array_gte)).map(combine_two_values) + }; + assert_eq(sorted, self.sorted_transformed_value_array); + + self.execute(); + } } #[test] fn assert_combined_sorted_transformed_value_array_asc_succeeds() { let builder = TestDataBuilder::new(); - - let hints = get_combined_order_hints_asc(builder.original_array_lt, builder.original_array_gte); - assert_eq(hints, builder.hints); - - let sorted = sort_by_counter_asc(array_merge(builder.original_array_lt, builder.original_array_gte)).map(transform); - assert_eq(sorted, builder.sorted_transformed_value_array); - - builder.execute(); + builder.check_and_execute(); } #[test] fn assert_combined_sorted_transformed_value_array_asc_without_prepended_counter_zeros_succeeds() { let builder = TestDataBuilder::new_without_prepended(); - - let hints = get_combined_order_hints_asc(builder.original_array_lt, builder.original_array_gte); - assert_eq(hints, builder.hints); - - let sorted = sort_by_counter_asc(array_merge(builder.original_array_lt, builder.original_array_gte)).map(transform); - assert_eq(sorted, builder.sorted_transformed_value_array); - - builder.execute(); + builder.check_and_execute(); } #[test(should_fail_with="incorrect transformed value")] @@ -308,7 +261,7 @@ mod tests { let mut builder = TestDataBuilder::new(); // Tweak the value at index 1. - builder.sorted_transformed_value_array[1].total += 1; + builder.sorted_transformed_value_array[1].value += 1; builder.execute(); } @@ -382,7 +335,7 @@ mod tests { let mut builder = TestDataBuilder::new(); // Clear an item. - builder.sorted_transformed_value_array[8] = TestValue::empty(); + builder.sorted_transformed_value_array[8] = TestCombinedValue::empty(); builder.hints[8] = CombinedOrderHint { counter: 0, original_index: 6 }; builder.execute(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array/get_combined_order_hints.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array/get_combined_order_hints.nr index 94ec60bbbf6..09ae1627c83 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array/get_combined_order_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array/get_combined_order_hints.nr @@ -20,7 +20,7 @@ impl Eq for CombinedOrderHint { } } -unconstrained fn count_private_items(array: [T; N]) -> u32 where T: Ordered + Empty + Eq { +unconstrained pub fn count_private_items(array: [T; N]) -> u32 where T: Ordered + Empty + Eq { let mut length = 0; for item in array { if !is_empty(item) & (item.counter() == 0) { @@ -30,7 +30,7 @@ unconstrained fn count_private_items(array: [T; N]) -> u32 where length } -pub fn get_combined_order_hints_asc( +unconstrained pub fn get_combined_order_hints_asc( array_lt: [T; N], array_gte: [T; N] ) -> [CombinedOrderHint; N] where T: Ordered + Eq + Empty { @@ -60,50 +60,38 @@ pub fn get_combined_order_hints_asc( mod tests { use crate::{ - abis::side_effect::Ordered, tests::utils::pad_end, traits::Empty, + tests::{types::TestValue, utils::pad_end}, utils::arrays::assert_combined_sorted_transformed_value_array::get_combined_order_hints::{CombinedOrderHint, get_combined_order_hints_asc} }; - struct TestItem { - value: Field, - counter: u32, - } - - impl Ordered for TestItem { - fn counter(self) -> u32 { - self.counter - } - } - - impl Eq for TestItem { - fn eq(self, other: Self) -> bool { - (self.value == other.value) & (self.counter == other.counter) - } - } - - impl Empty for TestItem { - fn empty() -> Self { - TestItem { value: 0, counter: 0 } - } + fn asc_to_equal( + array_lt: [TestValue; N], + array_gte: [TestValue; N], + expected: [CombinedOrderHint; N] + ) { + let hints = unsafe { + get_combined_order_hints_asc(array_lt, array_gte) + }; + assert_eq(hints, expected); } #[test] fn get_combined_order_hints_asc_full_non_empty() { let array_lt = pad_end( [ - TestItem { value: 600, counter: 9 }, - TestItem { value: 400, counter: 3 }, - TestItem { value: 500, counter: 6 } + TestValue { value: 600, counter: 9 }, + TestValue { value: 400, counter: 3 }, + TestValue { value: 500, counter: 6 } ], - TestItem::empty() + TestValue::empty() ); let array_gte = pad_end( [ - TestItem { value: 200, counter: 13 }, - TestItem { value: 100, counter: 19 }, - TestItem { value: 300, counter: 16 } + TestValue { value: 200, counter: 13 }, + TestValue { value: 100, counter: 19 }, + TestValue { value: 300, counter: 16 } ], - TestItem::empty() + TestValue::empty() ); let expected_hints = [ CombinedOrderHint { counter: 3, original_index: 1 }, @@ -113,19 +101,19 @@ mod tests { CombinedOrderHint { counter: 16, original_index: 2 }, CombinedOrderHint { counter: 19, original_index: 1 } ]; - assert_eq(get_combined_order_hints_asc(array_lt, array_gte), expected_hints); + asc_to_equal(array_lt, array_gte, expected_hints); } #[test] fn get_combined_order_hints_asc_padded_empty() { let array_lt = pad_end( [ - TestItem { value: 500, counter: 6 }, - TestItem { value: 400, counter: 3 } + TestValue { value: 500, counter: 6 }, + TestValue { value: 400, counter: 3 } ], - TestItem::empty() + TestValue::empty() ); - let array_gte = pad_end([TestItem { value: 100, counter: 19 }], TestItem::empty()); + let array_gte = pad_end([TestValue { value: 100, counter: 19 }], TestValue::empty()); let expected_hints = [ CombinedOrderHint { counter: 3, original_index: 1 }, CombinedOrderHint { counter: 6, original_index: 0 }, @@ -133,18 +121,18 @@ mod tests { CombinedOrderHint { counter: 0, original_index: 1 }, CombinedOrderHint { counter: 0, original_index: 2 } ]; - assert_eq(get_combined_order_hints_asc(array_lt, array_gte), expected_hints); + asc_to_equal(array_lt, array_gte, expected_hints); } #[test] fn get_combined_order_hints_asc_lt_empty() { - let array_lt = [TestItem::empty(); 4]; + let array_lt = [TestValue::empty(); 4]; let array_gte = pad_end( [ - TestItem { value: 200, counter: 13 }, - TestItem { value: 100, counter: 19 } + TestValue { value: 200, counter: 13 }, + TestValue { value: 100, counter: 19 } ], - TestItem::empty() + TestValue::empty() ); let expected_hints = [ CombinedOrderHint { counter: 13, original_index: 0 }, @@ -152,58 +140,58 @@ mod tests { CombinedOrderHint { counter: 0, original_index: 2 }, CombinedOrderHint { counter: 0, original_index: 3 } ]; - assert_eq(get_combined_order_hints_asc(array_lt, array_gte), expected_hints); + asc_to_equal(array_lt, array_gte, expected_hints); } #[test] fn get_combined_order_hints_asc_gte_empty() { let array_lt = pad_end( [ - TestItem { value: 400, counter: 3 }, - TestItem { value: 500, counter: 6 } + TestValue { value: 400, counter: 3 }, + TestValue { value: 500, counter: 6 } ], - TestItem::empty() + TestValue::empty() ); - let array_gte = [TestItem::empty(); 4]; + let array_gte = [TestValue::empty(); 4]; let expected_hints = [ CombinedOrderHint { counter: 3, original_index: 0 }, CombinedOrderHint { counter: 6, original_index: 1 }, CombinedOrderHint { counter: 0, original_index: 0 }, CombinedOrderHint { counter: 0, original_index: 1 } ]; - assert_eq(get_combined_order_hints_asc(array_lt, array_gte), expected_hints); + asc_to_equal(array_lt, array_gte, expected_hints); } #[test] fn get_combined_order_hints_asc_all_empty() { - let array_lt = [TestItem::empty(); 3]; - let array_gte = [TestItem::empty(); 3]; + let array_lt = [TestValue::empty(); 3]; + let array_gte = [TestValue::empty(); 3]; let expected_hints = [ CombinedOrderHint { counter: 0, original_index: 0 }, CombinedOrderHint { counter: 0, original_index: 1 }, CombinedOrderHint { counter: 0, original_index: 2 } ]; - assert_eq(get_combined_order_hints_asc(array_lt, array_gte), expected_hints); + asc_to_equal(array_lt, array_gte, expected_hints); } #[test] fn get_combined_order_hints_asc_prepended_zero_counters() { let array_lt = pad_end( [ - TestItem { value: 700, counter: 0 }, - TestItem { value: 500, counter: 0 }, - TestItem { value: 100, counter: 16 }, - TestItem { value: 400, counter: 13 } + TestValue { value: 700, counter: 0 }, + TestValue { value: 500, counter: 0 }, + TestValue { value: 100, counter: 16 }, + TestValue { value: 400, counter: 13 } ], - TestItem::empty() + TestValue::empty() ); let array_gte = pad_end( [ - TestItem { value: 300, counter: 0 }, - TestItem { value: 600, counter: 0 }, - TestItem { value: 200, counter: 19 } + TestValue { value: 300, counter: 0 }, + TestValue { value: 600, counter: 0 }, + TestValue { value: 200, counter: 19 } ], - TestItem::empty() + TestValue::empty() ); let expected_hints = [ CombinedOrderHint { counter: 0, original_index: 0 }, @@ -217,20 +205,20 @@ mod tests { CombinedOrderHint { counter: 0, original_index: 4 }, CombinedOrderHint { counter: 0, original_index: 5 } ]; - assert_eq(get_combined_order_hints_asc(array_lt, array_gte), expected_hints); + asc_to_equal(array_lt, array_gte, expected_hints); } #[test] fn get_combined_order_hints_asc_prepended_zero_counters_lt_empty() { - let array_lt = [TestItem::empty(); 6]; + let array_lt = [TestValue::empty(); 6]; let array_gte = pad_end( [ - TestItem { value: 300, counter: 0 }, - TestItem { value: 600, counter: 0 }, - TestItem { value: 200, counter: 19 }, - TestItem { value: 400, counter: 13 } + TestValue { value: 300, counter: 0 }, + TestValue { value: 600, counter: 0 }, + TestValue { value: 200, counter: 19 }, + TestValue { value: 400, counter: 13 } ], - TestItem::empty() + TestValue::empty() ); let expected_hints = [ CombinedOrderHint { counter: 0, original_index: 0 }, @@ -240,21 +228,21 @@ mod tests { CombinedOrderHint { counter: 0, original_index: 4 }, CombinedOrderHint { counter: 0, original_index: 5 } ]; - assert_eq(get_combined_order_hints_asc(array_lt, array_gte), expected_hints); + asc_to_equal(array_lt, array_gte, expected_hints); } #[test] fn get_combined_order_hints_asc_prepended_zero_counters_gte_empty() { let array_lt = pad_end( [ - TestItem { value: 300, counter: 0 }, - TestItem { value: 600, counter: 0 }, - TestItem { value: 200, counter: 19 }, - TestItem { value: 400, counter: 13 } + TestValue { value: 300, counter: 0 }, + TestValue { value: 600, counter: 0 }, + TestValue { value: 200, counter: 19 }, + TestValue { value: 400, counter: 13 } ], - TestItem::empty() + TestValue::empty() ); - let array_gte = [TestItem::empty(); 6]; + let array_gte = [TestValue::empty(); 6]; let expected_hints = [ CombinedOrderHint { counter: 0, original_index: 0 }, CombinedOrderHint { counter: 0, original_index: 1 }, @@ -263,7 +251,7 @@ mod tests { CombinedOrderHint { counter: 0, original_index: 0 }, CombinedOrderHint { counter: 0, original_index: 1 } ]; - assert_eq(get_combined_order_hints_asc(array_lt, array_gte), expected_hints); + asc_to_equal(array_lt, array_gte, expected_hints); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_transformed_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_transformed_array.nr new file mode 100644 index 00000000000..bd81809c9b9 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_transformed_array.nr @@ -0,0 +1,164 @@ +use crate::{traits::Empty, utils::arrays::array_length}; + +// original_array(_lt/_gte) must be valid, i.e. validate_array(original_array) == true +// This ensures that combined_array is valid when S can only be empty if and only if T is empty. +pub fn assert_combined_transformed_array( + original_array_lt: [T; N], + original_array_gte: [T; N], + combined_array: [S; N], + is_transformed: fn[Env](T, S) -> bool +) where T: Empty + Eq { + let num_lt = array_length(original_array_lt); + let mut is_lt = true; + for i in 0..N { + is_lt &= i != num_lt; + + let from = if is_lt { + original_array_lt[i] + } else { + original_array_gte[i - num_lt] + }; + + let to = combined_array[i]; + + assert(is_transformed(from, to), "hinted item in the commbined array does not match"); + } +} + +unconstrained pub fn combine_and_transform_arrays( + original_array_lt: [T; N], + original_array_gte: [T; N], + transform: fn[Env](T) -> S +) -> [S; N] where T: Empty + Eq { + let mut combined = original_array_lt.map(transform); + + let num_lt = array_length(original_array_lt); + for i in 0..N { + if i >= num_lt { + let from = original_array_gte[i - num_lt]; + combined[i] = transform(from); + } + } + + combined +} + +mod tests { + use crate::{ + tests::{types::{is_summed_from_two_values, sum_two_values, TestTwoValues, TestValue}, utils::pad_end}, + utils::arrays::assert_combined_transformed_array::{assert_combined_transformed_array, combine_and_transform_arrays} + }; + + struct TestBuilder { + original_array_lt: [TestTwoValues; N], + original_array_gte: [TestTwoValues; N], + combined_array: [TestValue; N], + } + + impl TestBuilder<10> { + pub fn new_empty() -> Self { + let original_array_lt = pad_end([], TestTwoValues::empty()); + let original_array_gte = pad_end([], TestTwoValues::empty()); + let combined_array = pad_end([], TestValue::empty()); + TestBuilder { original_array_lt, original_array_gte, combined_array } + } + + pub fn new() -> Self { + let original_array_lt = pad_end( + [ + TestTwoValues { value_1: 10, value_2: 1, counter: 2 }, + TestTwoValues { value_1: 20, value_2: 2, counter: 5 }, + TestTwoValues { value_1: 30, value_2: 3, counter: 3 } + ], + TestTwoValues::empty() + ); + + let original_array_gte = pad_end( + [ + TestTwoValues { value_1: 40, value_2: 4, counter: 1 }, + TestTwoValues { value_1: 50, value_2: 5, counter: 4 } + ], + TestTwoValues::empty() + ); + + let combined_array = pad_end( + [ + TestValue { value: 11, counter: 2 }, + TestValue { value: 22, counter: 5 }, + TestValue { value: 33, counter: 3 }, + TestValue { value: 44, counter: 1 }, + TestValue { value: 55, counter: 4 } + ], + TestValue::empty() + ); + + TestBuilder { original_array_lt, original_array_gte, combined_array } + } + + pub fn execute(self) { + assert_combined_transformed_array( + self.original_array_lt, + self.original_array_gte, + self.combined_array, + is_summed_from_two_values + ); + } + + pub fn check_and_execute(self) { + let combined = unsafe { + combine_and_transform_arrays( + self.original_array_lt, + self.original_array_gte, + sum_two_values + ) + }; + assert_eq(combined, self.combined_array); + + self.execute(); + } + } + + #[test] + fn assert_combined_transformed_array_empty_succeeds() { + let builder = TestBuilder::new_empty(); + builder.check_and_execute(); + } + + #[test] + fn assert_combined_transformed_array_succeeds() { + let builder = TestBuilder::new(); + builder.check_and_execute(); + } + + #[test(should_fail_with="hinted item in the commbined array does not match")] + fn assert_combined_transformed_array_extra_item_fails() { + let mut builder = TestBuilder::new(); + + // Add random value to an empty item. + builder.combined_array[7].value = 123; + + builder.execute(); + } + + #[test(should_fail_with="hinted item in the commbined array does not match")] + fn assert_combined_transformed_array_missing_item_fails() { + let mut builder = TestBuilder::new(); + + // Clear the last item. + builder.combined_array[4] = TestValue::empty(); + + builder.execute(); + } + + #[test(should_fail_with="hinted item in the commbined array does not match")] + fn assert_combined_transformed_array_unordered_fails() { + let mut builder = TestBuilder::new(); + + // Swap the two items. + let tmp = builder.combined_array[3]; + builder.combined_array[3] = builder.combined_array[1]; + builder.combined_array[1] = tmp; + + builder.execute(); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_deduped_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_deduped_array.nr new file mode 100644 index 00000000000..86db1994d58 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_deduped_array.nr @@ -0,0 +1,157 @@ +use crate::{abis::side_effect::{Inner, Overridable}, traits::{Empty, is_empty}}; + +// Check that deduped_array contains values that are not being overriden, i.e. override_counter == 0. +pub fn assert_deduped_array( + original_array: [S; N], + deduped_array: [T; N] +) where S: Overridable + Inner, T: Eq + Empty { + let mut num_added = 0; + for i in 0..original_array.len() { + let original = original_array[i]; + if original.override_counter() == 0 { + assert_eq(original.inner(), deduped_array[num_added], "mismatch deduped item"); + num_added += 1; + } + } + let mut should_be_empty = false; + for i in 0..original_array.len() { + should_be_empty |= i == num_added; + if should_be_empty { + assert(is_empty(deduped_array[i]), "empty items must be padded to the deduped array"); + } + } +} + +unconstrained pub fn dedupe_array(original_array: [S; N]) -> [T; N] where S: Overridable + Inner { + let mut deduped = BoundedVec::new(); + for i in 0..original_array.len() { + let original = original_array[i]; + if original.override_counter() == 0 { + deduped.push(original.inner()); + } + } + deduped.storage +} + +mod tests { + use crate::{ + abis::side_effect::{Inner, Overridable}, tests::{types::TestValue, utils::pad_end}, + traits::Empty, utils::arrays::assert_deduped_array::{assert_deduped_array, dedupe_array} + }; + + struct TestItem { + value: TestValue, + override_by: TestValue, + } + + impl Overridable for TestItem { + fn override_counter(self) -> u32 { + self.override_by.counter + } + } + + impl Inner for TestItem { + fn inner(self) -> TestValue { + self.value + } + } + + impl Empty for TestItem { + fn empty() -> Self { + TestItem { value: TestValue::empty(), override_by: TestValue::empty() } + } + } + + impl Eq for TestItem { + fn eq(self, other: Self) -> bool { + (self.value == other.value) & (self.override_by == other.override_by) + } + } + + global NUM_TEST_ITEMS = 10; + + struct TestBuilder { + original_array: [TestItem; NUM_TEST_ITEMS], + deduped_array: [TestValue; NUM_TEST_ITEMS], + } + + impl TestBuilder { + pub fn new_empty() -> Self { + let original_array = pad_end([], TestItem::empty()); + let deduped_array = pad_end([], TestValue::empty()); + TestBuilder { original_array, deduped_array } + } + + pub fn new() -> Self { + let values = [ + TestValue { value: 22, counter: 2 }, + TestValue { value: 11, counter: 1 }, + TestValue { value: 44, counter: 4 }, + TestValue { value: 11, counter: 6 }, + TestValue { value: 11, counter: 3 }, + TestValue { value: 33, counter: 5 } + ]; + let mut original_array = pad_end( + values.map(|value: TestValue| TestItem { value, override_by: TestValue::empty() }), + TestItem::empty() + ); + original_array[1].override_by = values[4]; + original_array[4].override_by = values[3]; + + let deduped_array = pad_end( + [ + values[0], + values[2], + values[3], + values[5] + ], + TestValue::empty() + ); + + TestBuilder { original_array, deduped_array } + } + + pub fn execute(self) { + assert_deduped_array(self.original_array, self.deduped_array); + } + + pub fn check_and_execute(self) { + let deduped = unsafe { + dedupe_array(self.original_array) + }; + assert_eq(self.deduped_array, deduped); + + self.execute(); + } + } + + #[test] + fn assert_deduped_array_empty_succeeds() { + let builder = TestBuilder::new_empty(); + builder.check_and_execute(); + } + + #[test] + fn assert_deduped_array_succeeds() { + let builder = TestBuilder::new(); + builder.check_and_execute(); + } + + #[test(should_fail_with="mismatch deduped item")] + fn assert_deduped_array_extra_item_fails() { + let mut builder = TestBuilder::new(); + + builder.deduped_array[7] = builder.original_array[1].inner(); + + builder.execute(); + } + + #[test(should_fail_with="empty items must be padded to the deduped array")] + fn assert_deduped_array_extra_item_at_end_fails() { + let mut builder = TestBuilder::new(); + + builder.deduped_array[NUM_TEST_ITEMS - 1] = builder.original_array[1].inner(); + + builder.execute(); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array.nr index dd0260be56a..4a4929c6bf4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array.nr @@ -38,80 +38,34 @@ pub fn assert_exposed_sorted_transformed_value_array( mod tests { use crate::{ - abis::side_effect::Ordered, traits::Empty, + tests::types::{is_combined_from_two_values, TestCombinedValue, TestTwoValues}, utils::arrays::{assert_exposed_sorted_transformed_value_array::{assert_exposed_sorted_transformed_value_array, get_order_hints::OrderHint}} }; - struct TestItem { - name: Field, - price: Field, - tax: Field, - counter: u32, - } - - impl Ordered for TestItem { - fn counter(self) -> u32 { - self.counter - } - } - - impl Empty for TestItem { - fn empty() -> Self { - TestItem { name: 0, price: 0, tax: 0, counter: 0 } - } - } - - impl Eq for TestItem { - fn eq(self, other: Self) -> bool { - (self.name == other.name) & (self.price == other.price) & (self.tax == other.tax) & (self.counter == other.counter) - } - } - - struct TestValue { - name: Field, - total: Field, - } - - impl Empty for TestValue { - fn empty() -> Self { - TestValue { name: 0, total: 0 } - } - } - - impl Eq for TestValue { - fn eq(self, other: Self) -> bool { - (self.name == other.name) & (self.total == other.total) - } - } - - fn is_transformed(item: TestItem, value: TestValue) -> bool { - (item.name == value.name) & ((item.price + item.tax) == value.total) - } - - struct TestDataBuilder { - original_array: [T; N], - exposed_sorted_transformed_value_array: [S; N], + struct TestDataBuilder { + original_array: [TestTwoValues; N], + exposed_sorted_transformed_value_array: [TestCombinedValue; N], hints: [OrderHint; N], } - impl TestDataBuilder { + impl TestDataBuilder<6> { pub fn new() -> Self { let original_array = [ - TestItem { name: 100, price: 10, tax: 5, counter: 44 }, - TestItem { name: 200, price: 20, tax: 6, counter: 22 }, - TestItem { name: 300, price: 30, tax: 7, counter: 11 }, - TestItem { name: 400, price: 40, tax: 8, counter: 33 }, - TestItem::empty(), - TestItem::empty() + TestTwoValues { value_1: 10, value_2: 5, counter: 44 }, + TestTwoValues { value_1: 20, value_2: 6, counter: 22 }, + TestTwoValues { value_1: 30, value_2: 7, counter: 11 }, + TestTwoValues { value_1: 40, value_2: 8, counter: 33 }, + TestTwoValues::empty(), + TestTwoValues::empty() ]; let exposed_sorted_transformed_value_array = [ - TestValue { name: 300, total: 37 }, - TestValue { name: 200, total: 26 }, - TestValue { name: 400, total: 48 }, - TestValue { name: 100, total: 15 }, - TestValue::empty(), - TestValue::empty() + TestCombinedValue { value: 37 }, + TestCombinedValue { value: 26 }, + TestCombinedValue { value: 48 }, + TestCombinedValue { value: 15 }, + TestCombinedValue::empty(), + TestCombinedValue::empty() ]; let hints = [ @@ -130,7 +84,7 @@ mod tests { assert_exposed_sorted_transformed_value_array( self.original_array, self.exposed_sorted_transformed_value_array, - is_transformed, + is_combined_from_two_values, self.hints ); } @@ -147,7 +101,7 @@ mod tests { let mut builder = TestDataBuilder::new(); // Tweak the value at index 1. - builder.exposed_sorted_transformed_value_array[1].total += 1; + builder.exposed_sorted_transformed_value_array[1].value += 1; builder.execute(); } @@ -202,7 +156,7 @@ mod tests { let mut builder = TestDataBuilder::new(); // Add a random item. - builder.exposed_sorted_transformed_value_array[4] = TestValue { name: 500, total: 10 }; + builder.exposed_sorted_transformed_value_array[4] = TestCombinedValue { value: 10 }; builder.execute(); } @@ -212,7 +166,7 @@ mod tests { let mut builder = TestDataBuilder::new(); // Add a random item. - builder.exposed_sorted_transformed_value_array[4] = TestValue { name: 500, total: 10 }; + builder.exposed_sorted_transformed_value_array[4] = TestCombinedValue { value: 10 }; // Change the hint to point to an empty item. builder.hints[4].sorted_index = 5; @@ -224,7 +178,7 @@ mod tests { let mut builder = TestDataBuilder::new(); // Remove an item. - builder.exposed_sorted_transformed_value_array[3] = TestValue::empty(); + builder.exposed_sorted_transformed_value_array[3] = TestCombinedValue::empty(); builder.execute(); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array/get_order_hints.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array/get_order_hints.nr index 6bfdca7a162..f5e6ba6200b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array/get_order_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array/get_order_hints.nr @@ -1,5 +1,5 @@ use crate::{ - abis::side_effect::Ordered, traits::{Empty, is_empty}, + abis::side_effect::Ordered, traits::Empty, utils::arrays::{ sort_by_counter::{compare_by_counter_empty_padded_asc, compare_by_counter_empty_padded_desc}, get_sorted_tuple::get_sorted_tuple @@ -23,90 +23,96 @@ impl Eq for OrderHint { } } -pub fn get_order_hints( +unconstrained pub fn get_order_hints( array: [T; N], ordering: fn(T, T) -> bool -) -> [OrderHint; N] where T: Ordered + Eq + Empty { +) -> [OrderHint; N] where T: Ordered { let sorted_tuples = get_sorted_tuple(array, ordering); let mut hints = [OrderHint::empty(); N]; for i in 0..N { let elem = sorted_tuples[i].elem; hints[i].counter = elem.counter(); - if !is_empty(elem) { - let original_index = sorted_tuples[i].original_index; - hints[original_index].sorted_index = i; - } else { - hints[i].sorted_index = i; - } + let original_index = sorted_tuples[i].original_index; + hints[original_index].sorted_index = i; } hints } -pub fn get_order_hints_asc(array: [T; N]) -> [OrderHint; N] where T: Ordered + Eq + Empty { +unconstrained pub fn get_order_hints_asc(array: [T; N]) -> [OrderHint; N] where T: Ordered + Eq + Empty { get_order_hints(array, compare_by_counter_empty_padded_asc) } -pub fn get_order_hints_desc(array: [T; N]) -> [OrderHint; N] where T: Ordered + Eq + Empty { +unconstrained pub fn get_order_hints_desc(array: [T; N]) -> [OrderHint; N] where T: Ordered + Eq + Empty { get_order_hints(array, compare_by_counter_empty_padded_desc) } mod tests { use crate::{ - abis::side_effect::Ordered, traits::Empty, + tests::{types::TestValue, utils::pad_end}, utils::arrays::assert_exposed_sorted_transformed_value_array::get_order_hints::{get_order_hints_asc, get_order_hints_desc, OrderHint} }; - struct TestItem { - value: Field, - counter: u32, + struct TestBuilder { + array: [TestValue; N], } - impl Ordered for TestItem { - fn counter(self) -> u32 { - self.counter + impl TestBuilder<3> { + pub fn new() -> Self { + let array = [ + TestValue { value: 100, counter: 9 }, + TestValue { value: 200, counter: 3 }, + TestValue { value: 300, counter: 6 } + ]; + TestBuilder { array } } } - impl Eq for TestItem { - fn eq(self, other: Self) -> bool { - (self.value == other.value) & (self.counter == other.counter) + impl TestBuilder<5> { + pub fn new_padded() -> Self { + let array = pad_end( + [ + TestValue { value: 100, counter: 9 }, + TestValue { value: 200, counter: 3 }, + TestValue { value: 300, counter: 6 } + ], + TestValue::empty() + ); + TestBuilder { array } } } - impl Empty for TestItem { - fn empty() -> Self { - TestItem { value: 0, counter: 0 } + impl TestBuilder { + pub fn asc_to_equal(self, expected: [OrderHint; N]) { + let hints = unsafe { + get_order_hints_asc(self.array) + }; + assert_eq(hints, expected); + } + + pub fn desc_to_equal(self, expected: [OrderHint; N]) { + let hints = unsafe { + get_order_hints_desc(self.array) + }; + assert_eq(hints, expected); } } #[test] fn get_order_hints_asc_full_non_empty() { - let array = [ - TestItem { value: 100, counter: 9 }, - TestItem { value: 200, counter: 3 }, - TestItem { value: 300, counter: 6 } - ]; - let hints = get_order_hints_asc(array); + let builder = TestBuilder::new(); let expected_hints = [ OrderHint { counter: 3, sorted_index: 2 }, OrderHint { counter: 6, sorted_index: 0 }, OrderHint { counter: 9, sorted_index: 1 } ]; - assert_eq(hints, expected_hints); + builder.asc_to_equal(expected_hints); } #[test] fn get_order_hints_asc_padded_empty() { - let array = [ - TestItem { value: 100, counter: 9 }, - TestItem { value: 200, counter: 3 }, - TestItem { value: 300, counter: 6 }, - TestItem::empty(), - TestItem::empty() - ]; - let hints = get_order_hints_asc(array); + let builder = TestBuilder::new_padded(); let expected_hints = [ OrderHint { counter: 3, sorted_index: 2 }, OrderHint { counter: 6, sorted_index: 0 }, @@ -114,35 +120,23 @@ mod tests { OrderHint { counter: 0, sorted_index: 3 }, OrderHint { counter: 0, sorted_index: 4 } ]; - assert_eq(hints, expected_hints); + builder.asc_to_equal(expected_hints); } #[test] fn get_order_hints_desc_full_non_empty() { - let array = [ - TestItem { value: 100, counter: 9 }, - TestItem { value: 200, counter: 3 }, - TestItem { value: 300, counter: 6 } - ]; - let hints = get_order_hints_desc(array); + let builder = TestBuilder::new(); let expected_hints = [ OrderHint { counter: 9, sorted_index: 0 }, OrderHint { counter: 6, sorted_index: 2 }, OrderHint { counter: 3, sorted_index: 1 } ]; - assert_eq(hints, expected_hints); + builder.desc_to_equal(expected_hints); } #[test] fn get_order_hints_desc_padded_empty() { - let array = [ - TestItem { value: 100, counter: 9 }, - TestItem { value: 200, counter: 3 }, - TestItem { value: 300, counter: 6 }, - TestItem::empty(), - TestItem::empty() - ]; - let hints = get_order_hints_desc(array); + let builder = TestBuilder::new_padded(); let expected_hints = [ OrderHint { counter: 9, sorted_index: 0 }, OrderHint { counter: 6, sorted_index: 2 }, @@ -150,7 +144,7 @@ mod tests { OrderHint { counter: 0, sorted_index: 3 }, OrderHint { counter: 0, sorted_index: 4 } ]; - assert_eq(hints, expected_hints); + builder.desc_to_equal(expected_hints); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_transformed_value_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_transformed_value_array.nr index c85f82b3ed6..a8be9895087 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_transformed_value_array.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_transformed_value_array.nr @@ -53,81 +53,32 @@ pub fn assert_sorted_transformed_value_array_capped_size( mod tests { use crate::{ - abis::side_effect::Ordered, traits::Empty, + tests::types::{is_summed_from_two_values, TestTwoValues, TestValue}, utils::arrays::{assert_sorted_transformed_value_array::{assert_sorted_transformed_value_array, assert_sorted_transformed_value_array_capped_size}} }; - struct TestItem { - name: Field, - price: Field, - tax: Field, - counter: u32, - } - - impl Empty for TestItem { - fn empty() -> Self { - TestItem { name: 0, price: 0, tax: 0, counter: 0 } - } - } - - impl Eq for TestItem { - fn eq(self, other: Self) -> bool { - (self.name == other.name) & (self.price == other.price) & (self.tax == other.tax) & (self.counter == other.counter) - } - } - - struct TestValue { - name: Field, - total: Field, - counter: u32, - } - - impl Ordered for TestValue { - fn counter(self) -> u32 { - self.counter - } - } - - impl Empty for TestValue { - fn empty() -> Self { - TestValue { name: 0, total: 0, counter: 0 } - } - } - - impl Eq for TestValue { - fn eq(self, other: Self) -> bool { - (self.name == other.name) & (self.total == other.total) & (self.counter == other.counter) - } - } - - fn is_transformed(item: TestItem, value: TestValue) -> bool { - (item.name == value.name) - & ((item.price + item.tax) == value.total) - & (item.counter == value.counter) - } - - struct TestDataBuilder { - original_array: [T; N], - sorted_transformed_value_array: [S; N], + struct TestDataBuilder { + original_array: [TestTwoValues; N], + sorted_transformed_value_array: [TestValue; N], sorted_indexes: [u32; N], } - impl TestDataBuilder { + impl TestDataBuilder<6> { pub fn new() -> Self { let original_array = [ - TestItem { name: 100, price: 10, tax: 5, counter: 44 }, - TestItem { name: 200, price: 20, tax: 6, counter: 22 }, - TestItem { name: 300, price: 30, tax: 7, counter: 11 }, - TestItem { name: 400, price: 40, tax: 8, counter: 33 }, - TestItem::empty(), - TestItem::empty() + TestTwoValues { value_1: 10, value_2: 5, counter: 44 }, + TestTwoValues { value_1: 20, value_2: 6, counter: 22 }, + TestTwoValues { value_1: 30, value_2: 7, counter: 11 }, + TestTwoValues { value_1: 40, value_2: 8, counter: 33 }, + TestTwoValues::empty(), + TestTwoValues::empty() ]; let sorted_transformed_value_array = [ - TestValue { name: 300, total: 37, counter: 11 }, - TestValue { name: 200, total: 26, counter: 22 }, - TestValue { name: 400, total: 48, counter: 33 }, - TestValue { name: 100, total: 15, counter: 44 }, + TestValue { value: 37, counter: 11 }, + TestValue { value: 26, counter: 22 }, + TestValue { value: 48, counter: 33 }, + TestValue { value: 15, counter: 44 }, TestValue::empty(), TestValue::empty() ]; @@ -141,7 +92,7 @@ mod tests { assert_sorted_transformed_value_array( self.original_array, self.sorted_transformed_value_array, - is_transformed, + is_summed_from_two_values, self.sorted_indexes ); } @@ -150,7 +101,7 @@ mod tests { assert_sorted_transformed_value_array_capped_size( self.original_array, self.sorted_transformed_value_array, - is_transformed, + is_summed_from_two_values, self.sorted_indexes, capped_size ); @@ -168,7 +119,7 @@ mod tests { let mut builder = TestDataBuilder::new(); // Tweak the value at index 1. - builder.sorted_transformed_value_array[1].total += 1; + builder.sorted_transformed_value_array[1].value += 1; builder.execute(); } @@ -198,7 +149,7 @@ mod tests { let mut builder = TestDataBuilder::new(); // Add a random item. - builder.sorted_transformed_value_array[4] = TestValue { name: 500, total: 10, counter: 55 }; + builder.sorted_transformed_value_array[4] = TestValue { value: 10, counter: 55 }; builder.execute(); } @@ -208,7 +159,7 @@ mod tests { let mut builder = TestDataBuilder::new(); // Add a random item. - builder.sorted_transformed_value_array[4] = TestValue { name: 500, total: 10, counter: 55 }; + builder.sorted_transformed_value_array[4] = TestValue { value: 10, counter: 55 }; // Change the hint to point to an empty item. builder.sorted_indexes[4] = 5; @@ -242,7 +193,7 @@ mod tests { let mut builder = TestDataBuilder::new(); // Add a random item outside of capped_size. - builder.sorted_transformed_value_array[4] = TestValue { name: 500, total: 10, counter: 55 }; + builder.sorted_transformed_value_array[4] = TestValue { value: 10, counter: 55 }; builder.execute_capped(4); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr index 5efe0c698d5..1e87d8f539e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr @@ -1,7 +1,7 @@ mod get_split_order_hints; use crate::{ - abis::side_effect::Ordered, traits::{Empty, is_empty}, + abis::side_effect::Ordered, traits::Empty, utils::arrays::{ array_length, assert_split_sorted_transformed_value_arrays::get_split_order_hints::SplitOrderHints, validate_array @@ -115,7 +115,7 @@ pub fn assert_split_sorted_transformed_value_arrays_desc( mod tests { use crate::{ - abis::side_effect::Ordered, traits::Empty, + tests::types::{combine_two_values, TestCombinedValue, TestTwoValues}, utils::arrays::{ assert_split_sorted_transformed_value_arrays::{ assert_split_sorted_transformed_value_arrays_asc, @@ -124,80 +124,34 @@ mod tests { } }; - struct TestItem { - name: Field, - price: Field, - tax: Field, - counter: u32, - } - - impl Ordered for TestItem { - fn counter(self) -> u32 { - self.counter - } - } - - impl Empty for TestItem { - fn empty() -> Self { - TestItem { name: 0, price: 0, tax: 0, counter: 0 } - } - } - - impl Eq for TestItem { - fn eq(self, other: Self) -> bool { - (self.name == other.name) & (self.price == other.price) & (self.tax == other.tax) & (self.counter == other.counter) - } - } - - struct TestValue { - name: Field, - total: Field, - } - - impl Empty for TestValue { - fn empty() -> Self { - TestValue { name: 0, total: 0 } - } - } - - impl Eq for TestValue { - fn eq(self, other: Self) -> bool { - (self.name == other.name) & (self.total == other.total) - } - } - - fn transform_value(item: TestItem) -> TestValue { - TestValue { name: item.name, total: item.price + item.tax } - } - global original_array = [ - TestItem { name: 0, price: 1, tax: 0, counter: 33 }, - TestItem { name: 1, price: 10, tax: 6, counter: 44 }, - TestItem { name: 2, price: 20, tax: 7, counter: 11 }, - TestItem { name: 3, price: 30, tax: 8, counter: 0 }, - TestItem { name: 4, price: 40, tax: 9, counter: 22 }, - TestItem::empty(), - TestItem::empty(), - TestItem::empty() + TestTwoValues { value_1: 1, value_2: 0, counter: 33 }, + TestTwoValues { value_1: 10, value_2: 6, counter: 44 }, + TestTwoValues { value_1: 20, value_2: 7, counter: 11 }, + TestTwoValues { value_1: 30, value_2: 8, counter: 0 }, + TestTwoValues { value_1: 40, value_2: 9, counter: 22 }, + TestTwoValues::empty(), + TestTwoValues::empty(), + TestTwoValues::empty() ]; - struct TestDataBuilder { - original_array: [T; N], - transformed_value_array: [S; N], - sorted_transformed_value_array_lt: [S; N], - sorted_transformed_value_array_gte: [S; N], + struct TestDataBuilder { + original_array: [TestTwoValues; N], + transformed_value_array: [TestCombinedValue; N], + sorted_transformed_value_array_lt: [TestCombinedValue; N], + sorted_transformed_value_array_gte: [TestCombinedValue; N], split_counter: u32, hints: SplitOrderHints, ascending: bool, } - impl TestDataBuilder { + impl TestDataBuilder<8> { pub fn empty() -> Self { TestDataBuilder { - original_array: [TestItem::empty(); 8], - transformed_value_array: [TestValue::empty(); 8], - sorted_transformed_value_array_lt: [TestValue::empty(); 8], - sorted_transformed_value_array_gte: [TestValue::empty(); 8], + original_array: [TestTwoValues::empty(); 8], + transformed_value_array: [TestCombinedValue::empty(); 8], + sorted_transformed_value_array_lt: [TestCombinedValue::empty(); 8], + sorted_transformed_value_array_gte: [TestCombinedValue::empty(); 8], split_counter: 0, hints: SplitOrderHints::empty(), ascending: false @@ -205,28 +159,28 @@ mod tests { } pub fn new() -> Self { - let transformed_value_array = original_array.map(|item: TestItem| transform_value(item)); + let transformed_value_array = original_array.map(|item: TestTwoValues| combine_two_values(item)); let split_counter = 15; let sorted_transformed_value_array_lt = [ - TestValue { name: 3, total: 38 }, - TestValue { name: 2, total: 27 }, - TestValue::empty(), - TestValue::empty(), - TestValue::empty(), - TestValue::empty(), - TestValue::empty(), - TestValue::empty() + TestCombinedValue { value: 38 }, + TestCombinedValue { value: 27 }, + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty() ]; let sorted_transformed_value_array_gte = [ - TestValue { name: 4, total: 49 }, - TestValue { name: 0, total: 1 }, - TestValue { name: 1, total: 16 }, - TestValue::empty(), - TestValue::empty(), - TestValue::empty(), - TestValue::empty(), - TestValue::empty() + TestCombinedValue { value: 49 }, + TestCombinedValue { value: 1 }, + TestCombinedValue { value: 16 }, + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty() ]; let hints = SplitOrderHints { sorted_counters_lt: [0, 11, 0, 0, 0, 0, 0, 0], @@ -246,28 +200,28 @@ mod tests { } pub fn new_desc() -> Self { - let transformed_value_array = original_array.map(|item: TestItem| transform_value(item)); + let transformed_value_array = original_array.map(|item: TestTwoValues| combine_two_values(item)); let split_counter = 15; let sorted_transformed_value_array_lt = [ - TestValue { name: 2, total: 27 }, - TestValue { name: 3, total: 38 }, - TestValue::empty(), - TestValue::empty(), - TestValue::empty(), - TestValue::empty(), - TestValue::empty(), - TestValue::empty() + TestCombinedValue { value: 27 }, + TestCombinedValue { value: 38 }, + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty() ]; let sorted_transformed_value_array_gte = [ - TestValue { name: 1, total: 16 }, - TestValue { name: 0, total: 1 }, - TestValue { name: 4, total: 49 }, - TestValue::empty(), - TestValue::empty(), - TestValue::empty(), - TestValue::empty(), - TestValue::empty() + TestCombinedValue { value: 16 }, + TestCombinedValue { value: 1 }, + TestCombinedValue { value: 49 }, + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty(), + TestCombinedValue::empty() ]; let hints = SplitOrderHints { sorted_counters_lt: [11, 0, 0, 0, 0, 0, 0, 0], @@ -353,7 +307,7 @@ mod tests { fn assert_split_sorted_transformed_value_array_asc_empty_extra_item_fails() { let mut builder = TestDataBuilder::empty(); - builder.sorted_transformed_value_array_lt[0].total = 1; + builder.sorted_transformed_value_array_lt[0].value = 1; builder.execute(); } @@ -362,7 +316,7 @@ mod tests { fn assert_split_sorted_transformed_value_array_asc_lt_wrong_sorted_value_fails() { let mut builder = TestDataBuilder::new(); - builder.sorted_transformed_value_array_lt[0].total += 1; + builder.sorted_transformed_value_array_lt[0].value += 1; builder.execute(); } @@ -416,7 +370,7 @@ mod tests { // Move the item with counter 44 from _gte to _lt. builder.sorted_transformed_value_array_lt[2] = builder.sorted_transformed_value_array_gte[2]; builder.hints.sorted_counters_lt[2] = 44; - builder.sorted_transformed_value_array_gte[2] = TestValue::empty(); + builder.sorted_transformed_value_array_gte[2] = TestCombinedValue::empty(); builder.hints.sorted_counters_lt[2] = 0; builder.update_sorted_index(44, 2); // Item of counter 44 is now at index 2 of the sorted array. @@ -482,7 +436,7 @@ mod tests { builder.update_sorted_index(counter, to_index); } // Empty the values at index 0. - builder.sorted_transformed_value_array_lt[0] = TestValue::empty(); + builder.sorted_transformed_value_array_lt[0] = TestCombinedValue::empty(); builder.hints.sorted_counters_lt[0] = 0; builder.execute(); @@ -502,7 +456,7 @@ mod tests { builder.update_sorted_index(counter, to_index); } // Empty the values at index 0. - builder.sorted_transformed_value_array_gte[0] = TestValue::empty(); + builder.sorted_transformed_value_array_gte[0] = TestCombinedValue::empty(); builder.hints.sorted_counters_gte[0] = 0; builder.execute(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays/get_split_order_hints.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays/get_split_order_hints.nr index f00a7650b30..285835edf14 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays/get_split_order_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays/get_split_order_hints.nr @@ -26,7 +26,7 @@ impl Eq for SplitOrderHints { } } -fn get_split_order_hints( +unconstrained fn get_split_order_hints( array: [T; N], split_counter: u32, ascending: bool @@ -67,14 +67,14 @@ fn get_split_order_hints( SplitOrderHints { sorted_counters_lt, sorted_counters_gte, sorted_indexes } } -pub fn get_split_order_hints_asc( +unconstrained pub fn get_split_order_hints_asc( array: [T; N], split_counter: u32 ) -> SplitOrderHints where T: Ordered + Eq + Empty { get_split_order_hints(array, split_counter, true) } -pub fn get_split_order_hints_desc( +unconstrained pub fn get_split_order_hints_desc( array: [T; N], split_counter: u32 ) -> SplitOrderHints where T: Ordered + Eq + Empty { @@ -83,197 +83,202 @@ pub fn get_split_order_hints_desc( mod tests { use crate::{ - abis::side_effect::Ordered, traits::Empty, + tests::{types::TestValue, utils::pad_end}, utils::arrays::assert_split_sorted_transformed_value_arrays::get_split_order_hints::{get_split_order_hints_asc, get_split_order_hints_desc, SplitOrderHints} }; - struct TestItem { - value: Field, - counter: u32, + global full_array = [ + TestValue { value: 100, counter: 11 }, + TestValue { value: 200, counter: 17 }, + TestValue { value: 300, counter: 7 }, + TestValue { value: 400, counter: 5 }, + TestValue { value: 500, counter: 13 } + ]; + + struct TestBuilder { + array: [TestValue; N], + split_counter: u32 } - impl Ordered for TestItem { - fn counter(self) -> u32 { - self.counter + impl TestBuilder<5> { + pub fn new() -> Self { + TestBuilder { array: full_array, split_counter: 0 } } } - impl Eq for TestItem { - fn eq(self, other: Self) -> bool { - (self.value == other.value) & (self.counter == other.counter) + impl TestBuilder<7> { + pub fn new_padded() -> Self { + TestBuilder { array: pad_end(full_array, TestValue::empty()), split_counter: 0 } } } - impl Empty for TestItem { - fn empty() -> Self { - TestItem { value: 0, counter: 0 } + impl TestBuilder { + pub fn asc_to_equal(self, expected: SplitOrderHints) { + let hints = unsafe { + get_split_order_hints_asc(self.array, self.split_counter) + }; + assert_eq(hints, expected); } - } - global full_array = [ - TestItem { value: 100, counter: 11 }, - TestItem { value: 200, counter: 17 }, - TestItem { value: 300, counter: 7 }, - TestItem { value: 400, counter: 5 }, - TestItem { value: 500, counter: 13 } - ]; - - global padded_array = [ - TestItem { value: 100, counter: 11 }, - TestItem { value: 200, counter: 17 }, - TestItem { value: 300, counter: 7 }, - TestItem { value: 400, counter: 5 }, - TestItem { value: 500, counter: 13 }, - TestItem::empty(), - TestItem::empty() - ]; + pub fn desc_to_equal(self, expected: SplitOrderHints) { + let hints = unsafe { + get_split_order_hints_desc(self.array, self.split_counter) + }; + assert_eq(hints, expected); + } + } // asc #[test] fn get_split_order_hints_asc_zero_split_counter_full() { - let split_counter = 0; - let hints = get_split_order_hints_asc(full_array, split_counter); + let builder = TestBuilder::new(); let expected_hints = SplitOrderHints { sorted_counters_lt: [0, 0, 0, 0, 0], sorted_counters_gte: [5, 7, 11, 13, 17], sorted_indexes: [2, 4, 1, 0, 3] }; - assert_eq(hints, expected_hints); + builder.asc_to_equal(expected_hints); } #[test] fn get_split_order_hints_asc_non_zero_split_counter_full() { - let split_counter = 9; - let hints = get_split_order_hints_asc(full_array, split_counter); + let mut builder = TestBuilder::new(); + builder.split_counter = 9; + let expected_hints = SplitOrderHints { sorted_counters_lt: [5, 7, 0, 0, 0], sorted_counters_gte: [11, 13, 17, 0, 0], sorted_indexes: [0, 2, 1, 0, 1] }; - assert_eq(hints, expected_hints); + builder.asc_to_equal(expected_hints); } #[test] fn get_split_order_hints_asc_non_zero_split_counter_equal_full() { - let split_counter = 11; // Equal one of the item's counter. - let hints = get_split_order_hints_asc(full_array, split_counter); + let mut builder = TestBuilder::new(); + builder.split_counter = 11; + let expected_hints = SplitOrderHints { sorted_counters_lt: [5, 7, 0, 0, 0], sorted_counters_gte: [11, 13, 17, 0, 0], sorted_indexes: [0, 2, 1, 0, 1] }; - assert_eq(hints, expected_hints); + builder.asc_to_equal(expected_hints); } #[test] fn get_split_order_hints_asc_zero_split_counter_padded_empty() { - let split_counter = 0; - let hints = get_split_order_hints_asc(padded_array, split_counter); + let builder = TestBuilder::new_padded(); + let expected_hints = SplitOrderHints { sorted_counters_lt: [0, 0, 0, 0, 0, 0, 0], sorted_counters_gte: [5, 7, 11, 13, 17, 0, 0], sorted_indexes: [2, 4, 1, 0, 3, 0, 0] }; - assert_eq(hints, expected_hints); + builder.asc_to_equal(expected_hints); } #[test] fn get_split_order_hints_asc_non_zero_split_counter_padded_empty() { - let split_counter = 9; - let hints = get_split_order_hints_asc(padded_array, split_counter); + let mut builder = TestBuilder::new_padded(); + builder.split_counter = 9; + let expected_hints = SplitOrderHints { sorted_counters_lt: [5, 7, 0, 0, 0, 0, 0], sorted_counters_gte: [11, 13, 17, 0, 0, 0, 0], sorted_indexes: [0, 2, 1, 0, 1, 0, 0] }; - assert_eq(hints, expected_hints); + builder.asc_to_equal(expected_hints); } #[test] fn get_split_order_hints_asc_non_zero_split_counter_equal_padded_empty() { - let split_counter = 11; - let hints = get_split_order_hints_asc(padded_array, split_counter); + let mut builder = TestBuilder::new_padded(); + builder.split_counter = 11; + let expected_hints = SplitOrderHints { sorted_counters_lt: [5, 7, 0, 0, 0, 0, 0], sorted_counters_gte: [11, 13, 17, 0, 0, 0, 0], sorted_indexes: [0, 2, 1, 0, 1, 0, 0] }; - assert_eq(hints, expected_hints); + builder.asc_to_equal(expected_hints); } // desc #[test] fn get_split_order_hints_desc_zero_split_counter_empty() { - let split_counter = 0; - let hints = get_split_order_hints_desc(full_array, split_counter); + let builder = TestBuilder::new(); let expected_hints = SplitOrderHints { sorted_counters_lt: [0, 0, 0, 0, 0], sorted_counters_gte: [17, 13, 11, 7, 5], sorted_indexes: [2, 0, 3, 4, 1] }; - assert_eq(hints, expected_hints); + builder.desc_to_equal(expected_hints); } #[test] fn get_split_order_hints_desc_non_zero_split_counter_empty() { - let split_counter = 9; - let hints = get_split_order_hints_desc(full_array, split_counter); + let mut builder = TestBuilder::new(); + builder.split_counter = 9; + let expected_hints = SplitOrderHints { sorted_counters_lt: [7, 5, 0, 0, 0], sorted_counters_gte: [17, 13, 11, 0, 0], sorted_indexes: [2, 0, 0, 1, 1] }; - assert_eq(hints, expected_hints); + builder.desc_to_equal(expected_hints); } #[test] fn get_split_order_hints_desc_non_zero_split_counter_equal_empty() { - let split_counter = 11; - let hints = get_split_order_hints_desc(full_array, split_counter); + let mut builder = TestBuilder::new(); + builder.split_counter = 11; + let expected_hints = SplitOrderHints { sorted_counters_lt: [7, 5, 0, 0, 0], sorted_counters_gte: [17, 13, 11, 0, 0], sorted_indexes: [2, 0, 0, 1, 1] }; - assert_eq(hints, expected_hints); + builder.desc_to_equal(expected_hints); } #[test] fn get_split_order_hints_desc_zero_split_counter_padded_empty() { - let split_counter = 0; - let hints = get_split_order_hints_desc(padded_array, split_counter); + let builder = TestBuilder::new_padded(); let expected_hints = SplitOrderHints { sorted_counters_lt: [0, 0, 0, 0, 0, 0, 0], sorted_counters_gte: [17, 13, 11, 7, 5, 0, 0], sorted_indexes: [2, 0, 3, 4, 1, 0, 0] }; - assert_eq(hints, expected_hints); + builder.desc_to_equal(expected_hints); } #[test] fn get_split_order_hints_desc_non_zero_split_counter_padded_empty() { - let split_counter = 9; - let hints = get_split_order_hints_desc(padded_array, split_counter); + let mut builder = TestBuilder::new_padded(); + builder.split_counter = 9; + let expected_hints = SplitOrderHints { sorted_counters_lt: [7, 5, 0, 0, 0, 0, 0], sorted_counters_gte: [17, 13, 11, 0, 0, 0, 0], sorted_indexes: [2, 0, 0, 1, 1, 0, 0] }; - assert_eq(hints, expected_hints); + builder.desc_to_equal(expected_hints); } #[test] fn get_split_order_hints_desc_non_zero_split_counter_equal_padded_empty() { - let split_counter = 11; - let hints = get_split_order_hints_desc(padded_array, split_counter); + let mut builder = TestBuilder::new_padded(); + builder.split_counter = 11; + let expected_hints = SplitOrderHints { sorted_counters_lt: [7, 5, 0, 0, 0, 0, 0], sorted_counters_gte: [17, 13, 11, 0, 0, 0, 0], sorted_indexes: [2, 0, 0, 1, 1, 0, 0] }; - assert_eq(hints, expected_hints); + builder.desc_to_equal(expected_hints); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_transformed_value_arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_transformed_value_arrays.nr index c1927035aae..be6f88970f5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_transformed_value_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_transformed_value_arrays.nr @@ -42,13 +42,6 @@ pub fn assert_split_transformed_value_arrays_with_hint( } } -unconstrained fn get_num_non_revertibles( - sorted_array: [T; N], - split_counter: u32 -) -> u32 where T: Ordered { - find_index_hint(sorted_array, |n: T| n.counter() >= split_counter) -} - pub fn assert_split_transformed_value_arrays( sorted_array: [T; N], transformed_value_array_lt: [S; N], // Values whose counters are less than the split counter. @@ -56,7 +49,9 @@ pub fn assert_split_transformed_value_arrays( is_transformed: fn[Env](T, S) -> bool, split_counter: u32 ) where T: Ordered + Empty + Eq, S: Empty + Eq { - let num_non_revertibles = get_num_non_revertibles(sorted_array, split_counter); + let num_non_revertibles = unsafe { + find_index_hint(sorted_array, |n: T| n.counter() >= split_counter) + }; assert_split_transformed_value_arrays_with_hint( sorted_array, @@ -70,41 +65,18 @@ pub fn assert_split_transformed_value_arrays( mod tests { use crate::{ - abis::side_effect::Ordered, tests::utils::pad_end, traits::Empty, + tests::{types::TestValue, utils::pad_end}, utils::arrays::assert_split_transformed_value_arrays::{assert_split_transformed_value_arrays, assert_split_transformed_value_arrays_with_hint} }; - struct TestItem { - value: Field, - counter: u32, - } - - impl Ordered for TestItem { - fn counter(self) -> u32 { - self.counter - } - } - - impl Eq for TestItem { - fn eq(self, other: Self) -> bool { - (self.value == other.value) & (self.counter == other.counter) - } - } - - impl Empty for TestItem { - fn empty() -> Self { - TestItem { value: 0, counter: 0 } - } - } - global NUM_TEST_ITEMS = 5; - fn is_transformed(from: TestItem, to: Field) -> bool { + fn is_transformed(from: TestValue, to: Field) -> bool { from.value == to } struct TestBuilder { - sorted_array: [TestItem; NUM_TEST_ITEMS], + sorted_array: [TestValue; NUM_TEST_ITEMS], transformed_value_array_lt: [Field; NUM_TEST_ITEMS], transformed_value_array_gte: [Field; NUM_TEST_ITEMS], split_counter: u32 @@ -113,11 +85,11 @@ mod tests { impl TestBuilder { pub fn new() -> Self { let sorted_array = [ - TestItem { value: 40, counter: 2 }, - TestItem { value: 30, counter: 7 }, - TestItem { value: 80, counter: 11 }, - TestItem { value: 10, counter: 13 }, - TestItem { value: 50, counter: 29 } + TestValue { value: 40, counter: 2 }, + TestValue { value: 30, counter: 7 }, + TestValue { value: 80, counter: 11 }, + TestValue { value: 10, counter: 13 }, + TestValue { value: 50, counter: 29 } ]; let transformed_value_array_lt = pad_end([40, 30, 80], 0); @@ -159,7 +131,7 @@ mod tests { fn assert_split_transformed_value_arrays_empty_succeeds() { let mut builder = TestBuilder::new(); - builder.sorted_array = [TestItem::empty(); NUM_TEST_ITEMS]; + builder.sorted_array = [TestValue::empty(); NUM_TEST_ITEMS]; builder.transformed_value_array_lt = [0; NUM_TEST_ITEMS]; builder.transformed_value_array_gte = [0; NUM_TEST_ITEMS]; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_hints.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_hints.nr deleted file mode 100644 index 9e6a490a008..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_hints.nr +++ /dev/null @@ -1,56 +0,0 @@ -use crate::{traits::{Empty, is_empty}, utils::arrays::{get_sorted_tuple::{get_sorted_tuple, SortedTuple}}}; - -struct SortedResult { - sorted_array: [T; N], - sorted_index_hints: [u32; N], -} - -pub fn get_sorted_hints( - values: [T; N], - ordering: fn(T, T) -> bool -) -> SortedResult where T: Eq + Empty { - let sorted = get_sorted_tuple(values, ordering); - - let sorted_array = sorted.map(|t: SortedTuple| t.elem); - let mut sorted_index_hints = [0; N]; - for i in 0..N { - if !is_empty(sorted[i].elem) { - let original_index = sorted[i].original_index; - sorted_index_hints[original_index] = i; - } - } - - SortedResult { sorted_array, sorted_index_hints } -} - -#[test] -fn get_sorted_hints_asc_non_padded() { - let values = [40, 60, 20, 50]; - let res = get_sorted_hints(values, |a: Field, b: Field| a.lt(b)); - assert_eq(res.sorted_array, [20, 40, 50, 60]); - assert_eq(res.sorted_index_hints, [1, 3, 0, 2]); -} - -#[test] -fn get_sorted_hints_desc_non_padded() { - let values = [40, 20, 60, 50]; - let res = get_sorted_hints(values, |a: Field, b: Field| b.lt(a)); - assert_eq(res.sorted_array, [60, 50, 40, 20]); - assert_eq(res.sorted_index_hints, [2, 3, 0, 1]); -} - -#[test] -fn get_sorted_hints_asc_padded() { - let values = [40, 60, 20, 50, 0, 0]; - let res = get_sorted_hints(values, |a: Field, b: Field| (b == 0) | ((a != 0) & a.lt(b))); - assert_eq(res.sorted_array, [20, 40, 50, 60, 0, 0]); - assert_eq(res.sorted_index_hints, [1, 3, 0, 2, 0, 0]); -} - -#[test] -fn get_sorted_hints_desc_padded() { - let values = [40, 20, 60, 50, 0, 0]; - let res = get_sorted_hints(values, |a: Field, b: Field| (b == 0) | b.lt(a)); - assert_eq(res.sorted_array, [60, 50, 40, 20, 0, 0]); - assert_eq(res.sorted_index_hints, [2, 3, 0, 1, 0, 0]); -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_result.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_result.nr new file mode 100644 index 00000000000..7356f9c5ce3 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_result.nr @@ -0,0 +1,67 @@ +use crate::{utils::arrays::{get_sorted_tuple::{get_sorted_tuple, SortedTuple}}}; + +struct SortedResult { + sorted_array: [T; N], + sorted_index_hints: [u32; N], + original_index_hints: [u32; N], +} + +unconstrained pub fn get_sorted_result( + values: [T; N], + ordering: fn(T, T) -> bool +) -> SortedResult { + let sorted = get_sorted_tuple(values, ordering); + + let sorted_array = sorted.map(|t: SortedTuple| t.elem); + let original_index_hints = sorted.map(|t: SortedTuple| t.original_index); + let mut sorted_index_hints = [0; N]; + for i in 0..N { + let original_index = sorted[i].original_index; + sorted_index_hints[original_index] = i; + } + + SortedResult { sorted_array, sorted_index_hints, original_index_hints } +} + +#[test] +fn get_sorted_hints_asc_non_padded() { + let values = [40, 60, 20, 50]; + let res = unsafe { + get_sorted_result(values, |a: u32, b: u32| a < b) + }; + assert_eq(res.sorted_array, [20, 40, 50, 60]); + assert_eq(res.sorted_index_hints, [1, 3, 0, 2]); + assert_eq(res.original_index_hints, [2, 0, 3, 1]); +} + +#[test] +fn get_sorted_hints_desc_non_padded() { + let values = [40, 20, 60, 50]; + let res = unsafe { + get_sorted_result(values, |a: u32, b: u32| b < a) + }; + assert_eq(res.sorted_array, [60, 50, 40, 20]); + assert_eq(res.sorted_index_hints, [2, 3, 0, 1]); +} + +#[test] +fn get_sorted_hints_asc_padded() { + let values = [40, 60, 20, 50, 0, 0]; + let res = unsafe { + get_sorted_result(values, |a: u32, b: u32| (a != 0) & ((b == 0) | (a < b))) + }; + assert_eq(res.sorted_array, [20, 40, 50, 60, 0, 0]); + assert_eq(res.sorted_index_hints, [1, 3, 0, 2, 4, 5]); + assert_eq(res.original_index_hints, [2, 0, 3, 1, 4, 5]); +} + +#[test] +fn get_sorted_hints_desc_padded() { + let values = [40, 60, 20, 50, 0, 0]; + let res = unsafe { + get_sorted_result(values, |a: u32, b: u32| (a != 0) & ((b == 0) | (b < a))) + }; + assert_eq(res.sorted_array, [60, 50, 40, 20, 0, 0]); + assert_eq(res.sorted_index_hints, [2, 0, 3, 1, 4, 5]); + assert_eq(res.original_index_hints, [1, 3, 0, 2, 4, 5]); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_tuple.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_tuple.nr index f7d48a6aea9..204d90c1fc9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_tuple.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_tuple.nr @@ -5,10 +5,7 @@ struct SortedTuple { original_index: u32, } -pub fn get_sorted_tuple( - array: [T; N], - ordering: fn[Env](T, T) -> bool -) -> [SortedTuple; N] { +unconstrained pub fn get_sorted_tuple(array: [T; N], ordering: fn[Env](T, T) -> bool) -> [SortedTuple; N] { let mut tuples = [SortedTuple { elem: array[0], original_index: 0 }; N]; for i in 0..N { tuples[i] = SortedTuple { @@ -31,7 +28,9 @@ fn get_sorted_tuple_asc() { SortedTuple { elem: 5, original_index: 3 }, SortedTuple { elem: 9, original_index: 2 } ]; - let sorted = get_sorted_tuple(original, |a: u64, b: u64| a < b); + let sorted = unsafe { + get_sorted_tuple(original, |a: u64, b: u64| a < b) + }; for i in 0..4 { assert_eq(sorted[i].elem, expected[i].elem); assert_eq(sorted[i].original_index, expected[i].original_index); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by.nr index cb4052431d7..0b6e155be74 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by.nr @@ -1,12 +1,18 @@ use crate::utils::arrays::find_index_hint; -// Copied from the stdlib Array.sort_via, but this one doesn't use `ordering` to check that the array is sorted. -pub fn sort_by(array: [T; N], ordering: fn[Env](T, T) -> bool) -> [T; N] { +// Copied from the stdlib Array.sort_via. +// But this one doesn't use `ordering` to check that the array is sorted. +// This is to allow preserving the order of equal values. +unconstrained pub fn sort_by(array: [T; N], ordering: fn[Env](T, T) -> bool) -> [T; N] { let mut result = array; - let sorted_index = array.get_sorting_index(ordering); + let sorted_index = unsafe { + array.get_sorting_index(ordering) + }; // Ensure the indexes are correct for i in 0..N { - let pos = find_index_hint(sorted_index, |index: u32| index == i); + let pos = unsafe { + find_index_hint(sorted_index, |index: u32| index == i) + }; assert(sorted_index[pos] == i); } // Sort the array using the indexes diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by_counter.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by_counter.nr index b23a317e59a..dd07448eaee 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by_counter.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by_counter.nr @@ -8,67 +8,50 @@ pub fn compare_by_counter_empty_padded_desc(a: T, b: T) -> bool where T: Orde !is_empty(a) & (is_empty(b) | (a.counter() >= b.counter())) } -pub fn sort_by_counter_asc(array: [T; N]) -> [T; N] where T: Ordered + Empty + Eq { +unconstrained pub fn sort_by_counter_asc(array: [T; N]) -> [T; N] where T: Ordered + Empty + Eq { sort_by(array, compare_by_counter_empty_padded_asc) } -pub fn sort_by_counter_desc(array: [T; N]) -> [T; N] where T: Ordered + Empty + Eq { +unconstrained pub fn sort_by_counter_desc(array: [T; N]) -> [T; N] where T: Ordered + Empty + Eq { sort_by(array, compare_by_counter_empty_padded_desc) } mod tests { use crate::{ - abis::side_effect::Ordered, traits::Empty, + tests::types::TestValue, utils::arrays::sort_by_counter::{ compare_by_counter_empty_padded_asc, compare_by_counter_empty_padded_desc, sort_by_counter_asc, sort_by_counter_desc } }; - struct TestItem { - value: u32, - counter: u32, + fn asc_values_to_equal(values: [u32; N], expected: [u32; N]) { + let items = values.map(|value| TestValue { value: value as Field, counter: value }); + let sorted = unsafe { + sort_by_counter_asc(items).map(|item: TestValue| item.counter) + }; + assert_eq(sorted, expected); } - impl Ordered for TestItem { - fn counter(self) -> u32 { - self.counter - } - } - - impl Eq for TestItem { - fn eq(self, other: Self) -> bool { - (self.value == other.value) & (self.counter == other.counter) - } - } - - impl Empty for TestItem { - fn empty() -> Self { - TestItem { value: 0, counter: 0 } - } - } - - fn sort_by_values_asc(values: [u32; N]) -> [u32; N] { - let items = values.map(|value| TestItem { value, counter: value }); - sort_by_counter_asc(items).map(|item: TestItem| item.value) - } - - fn sort_by_values_desc(values: [u32; N]) -> [u32; N] { - let items = values.map(|value| TestItem { value, counter: value }); - sort_by_counter_desc(items).map(|item: TestItem| item.value) + fn desc_values_to_equal(values: [u32; N], expected: [u32; N]) { + let items = values.map(|value| TestValue { value: value as Field, counter: value }); + let sorted = unsafe { + sort_by_counter_desc(items).map(|item: TestValue| item.counter) + }; + assert_eq(sorted, expected); } fn compare_test_items_asc(value_1: u32, value_2: u32) -> bool { compare_by_counter_empty_padded_asc( - TestItem { value: value_1, counter: value_1 }, - TestItem { value: value_2, counter: value_2 } + TestValue { value: value_1 as Field, counter: value_1 }, + TestValue { value: value_2 as Field, counter: value_2 } ) } fn compare_test_items_desc(value_1: u32, value_2: u32) -> bool { compare_by_counter_empty_padded_desc( - TestItem { value: value_1, counter: value_1 }, - TestItem { value: value_2, counter: value_2 } + TestValue { value: value_1 as Field, counter: value_1 }, + TestValue { value: value_2 as Field, counter: value_2 } ) } @@ -90,71 +73,73 @@ mod tests { #[test] fn sort_by_counter_asc_full_non_empty() { - let sorted = sort_by_values_asc([4, 2, 1, 3, 5]); - assert_eq(sorted, [1, 2, 3, 4, 5]); + asc_values_to_equal([4, 2, 1, 3, 5], [1, 2, 3, 4, 5]); } #[test] fn sort_by_counter_desc_full_non_empty() { - let sorted = sort_by_values_desc([4, 2, 1, 3, 5]); - assert_eq(sorted, [5, 4, 3, 2, 1]); + desc_values_to_equal([4, 2, 1, 3, 5], [5, 4, 3, 2, 1]); } #[test] fn sort_by_counter_asc_padded_empty() { - let sorted = sort_by_values_asc([4, 2, 0, 0, 1, 0, 3, 5]); - assert_eq(sorted, [1, 2, 3, 4, 5, 0, 0, 0]); + asc_values_to_equal([4, 2, 0, 0, 1, 0, 3, 5], [1, 2, 3, 4, 5, 0, 0, 0]); } #[test] fn sort_by_counter_desc_padded_empty() { - let sorted = sort_by_values_desc([4, 2, 0, 0, 1, 0, 3, 5]); - assert_eq(sorted, [5, 4, 3, 2, 1, 0, 0, 0]); + desc_values_to_equal([4, 2, 0, 0, 1, 0, 3, 5], [5, 4, 3, 2, 1, 0, 0, 0]); } #[test] fn sort_by_counter_asc_with_zero_counters() { let original = [ - TestItem { value: 55, counter: 1 }, - TestItem { value: 11, counter: 0 }, - TestItem { value: 33, counter: 2 }, - TestItem { value: 44, counter: 0 }, - TestItem { value: 22, counter: 0 }, - TestItem::empty(), - TestItem::empty() + TestValue { value: 55, counter: 1 }, + TestValue { value: 11, counter: 0 }, + TestValue { value: 33, counter: 2 }, + TestValue { value: 44, counter: 0 }, + TestValue { value: 22, counter: 0 }, + TestValue::empty(), + TestValue::empty() ]; let expected = [ - TestItem { value: 11, counter: 0 }, - TestItem { value: 44, counter: 0 }, - TestItem { value: 22, counter: 0 }, - TestItem { value: 55, counter: 1 }, - TestItem { value: 33, counter: 2 }, - TestItem::empty(), - TestItem::empty() + TestValue { value: 11, counter: 0 }, + TestValue { value: 44, counter: 0 }, + TestValue { value: 22, counter: 0 }, + TestValue { value: 55, counter: 1 }, + TestValue { value: 33, counter: 2 }, + TestValue::empty(), + TestValue::empty() ]; - assert_eq(sort_by_counter_asc(original), expected); + let sorted = unsafe { + sort_by_counter_asc(original) + }; + assert_eq(sorted, expected); } #[test] fn sort_by_counter_desc_with_zero_counters() { let original = [ - TestItem { value: 55, counter: 1 }, - TestItem { value: 11, counter: 0 }, - TestItem { value: 33, counter: 2 }, - TestItem { value: 44, counter: 0 }, - TestItem { value: 22, counter: 0 }, - TestItem::empty(), - TestItem::empty() + TestValue { value: 55, counter: 1 }, + TestValue { value: 11, counter: 0 }, + TestValue { value: 33, counter: 2 }, + TestValue { value: 44, counter: 0 }, + TestValue { value: 22, counter: 0 }, + TestValue::empty(), + TestValue::empty() ]; let expected = [ - TestItem { value: 33, counter: 2 }, - TestItem { value: 55, counter: 1 }, - TestItem { value: 22, counter: 0 }, - TestItem { value: 44, counter: 0 }, - TestItem { value: 11, counter: 0 }, - TestItem::empty(), - TestItem::empty() + TestValue { value: 33, counter: 2 }, + TestValue { value: 55, counter: 1 }, + TestValue { value: 22, counter: 0 }, + TestValue { value: 44, counter: 0 }, + TestValue { value: 11, counter: 0 }, + TestValue::empty(), + TestValue::empty() ]; - assert_eq(sort_by_counter_desc(original), expected); + let sorted = unsafe { + sort_by_counter_desc(original) + }; + assert_eq(sorted, expected); } } diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index 0ccf7e4639d..ef5baf076a0 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -610,8 +610,8 @@ namespace Program { struct CalldataCopy { Program::MemoryAddress destination_address; - uint64_t size; - uint64_t offset; + Program::MemoryAddress size_address; + Program::MemoryAddress offset_address; friend bool operator==(const CalldataCopy&, const CalldataCopy&); std::vector bincodeSerialize() const; @@ -5278,8 +5278,8 @@ namespace Program { inline bool operator==(const BrilligOpcode::CalldataCopy &lhs, const BrilligOpcode::CalldataCopy &rhs) { if (!(lhs.destination_address == rhs.destination_address)) { return false; } - if (!(lhs.size == rhs.size)) { return false; } - if (!(lhs.offset == rhs.offset)) { return false; } + if (!(lhs.size_address == rhs.size_address)) { return false; } + if (!(lhs.offset_address == rhs.offset_address)) { return false; } return true; } @@ -5304,8 +5304,8 @@ template <> template void serde::Serializable::serialize(const Program::BrilligOpcode::CalldataCopy &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination_address, serializer); - serde::Serializable::serialize(obj.size, serializer); - serde::Serializable::serialize(obj.offset, serializer); + serde::Serializable::serialize(obj.size_address, serializer); + serde::Serializable::serialize(obj.offset_address, serializer); } template <> @@ -5313,8 +5313,8 @@ template Program::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize(Deserializer &deserializer) { Program::BrilligOpcode::CalldataCopy obj; obj.destination_address = serde::Deserializable::deserialize(deserializer); - obj.size = serde::Deserializable::deserialize(deserializer); - obj.offset = serde::Deserializable::deserialize(deserializer); + obj.size_address = serde::Deserializable::deserialize(deserializer); + obj.offset_address = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs index 7bed57e22a0..838886a03ce 100644 --- a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs @@ -164,10 +164,20 @@ fn simple_brillig_foreign_call() { let brillig_bytecode = BrilligBytecode { bytecode: vec![ + brillig::Opcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(1_usize), + }, + brillig::Opcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0_usize), + }, brillig::Opcode::CalldataCopy { destination_address: MemoryAddress(0), - size: 1, - offset: 0, + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), }, brillig::Opcode::ForeignCall { function: "invert".into(), @@ -204,11 +214,12 @@ fn simple_brillig_foreign_call() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 80, 49, 10, 192, 32, 12, 52, 45, 45, 133, 110, 190, - 68, 127, 224, 103, 28, 92, 28, 68, 124, 191, 130, 9, 4, 137, 46, 122, 16, 46, 119, 7, 33, - 9, 168, 142, 175, 21, 96, 255, 32, 147, 230, 32, 207, 33, 155, 61, 88, 56, 55, 203, 240, - 125, 175, 177, 1, 110, 170, 197, 101, 55, 242, 43, 100, 132, 159, 229, 33, 22, 159, 242, - 234, 87, 51, 45, 121, 90, 200, 42, 48, 209, 35, 111, 164, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 49, 10, 128, 48, 12, 108, 196, 138, 224, 230, + 75, 226, 15, 252, 140, 131, 139, 131, 136, 239, 111, 161, 9, 28, 165, 205, 210, 28, 132, + 36, 119, 16, 114, 9, 133, 130, 53, 7, 73, 29, 37, 107, 143, 80, 238, 148, 204, 99, 56, 200, + 111, 22, 227, 190, 83, 93, 16, 146, 193, 112, 22, 225, 34, 168, 205, 142, 174, 241, 218, + 206, 179, 121, 49, 188, 109, 57, 84, 191, 159, 255, 122, 63, 235, 199, 189, 190, 197, 237, + 13, 45, 1, 20, 245, 146, 30, 92, 2, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -230,20 +241,40 @@ fn complex_brillig_foreign_call() { let brillig_bytecode = BrilligBytecode { bytecode: vec![ + brillig::Opcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(3_usize), + }, + brillig::Opcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0_usize), + }, brillig::Opcode::CalldataCopy { destination_address: MemoryAddress(32), - size: 3, - offset: 0, + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), }, brillig::Opcode::Const { destination: MemoryAddress(0), value: FieldElement::from(32_usize), bit_size: BitSize::Integer(IntegerBitSize::U32), }, + brillig::Opcode::Const { + destination: MemoryAddress(3), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(1_usize), + }, + brillig::Opcode::Const { + destination: MemoryAddress(4), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(3_usize), + }, brillig::Opcode::CalldataCopy { destination_address: MemoryAddress(1), - size: 1, - offset: 3, + size_address: MemoryAddress(3), + offset_address: MemoryAddress(4), }, // Oracles are named 'foreign calls' in brillig brillig::Opcode::ForeignCall { @@ -307,15 +338,17 @@ fn complex_brillig_foreign_call() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 77, 90, 199, 17, 102, 55, - 39, 24, 152, 57, 64, 199, 19, 120, 23, 113, 167, 232, 210, 227, 107, 49, 98, 124, 22, 92, - 88, 65, 31, 148, 244, 147, 207, 75, 66, 202, 52, 33, 27, 23, 203, 254, 33, 210, 136, 244, - 247, 150, 214, 152, 117, 11, 145, 238, 24, 254, 28, 207, 151, 59, 139, 163, 185, 1, 71, - 123, 2, 71, 82, 253, 191, 96, 191, 99, 246, 37, 106, 253, 108, 96, 126, 18, 154, 230, 43, - 149, 243, 83, 100, 134, 133, 246, 70, 134, 182, 131, 183, 2, 78, 172, 247, 250, 1, 71, 132, - 17, 196, 46, 137, 150, 105, 238, 82, 197, 133, 33, 254, 75, 101, 89, 182, 77, 87, 87, 189, - 5, 85, 164, 251, 85, 251, 31, 188, 51, 216, 161, 173, 134, 254, 192, 66, 186, 28, 208, 219, - 243, 253, 166, 165, 196, 115, 217, 7, 253, 216, 100, 109, 69, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 81, 14, 194, 48, 8, 133, 118, 206, 26, 255, 60, + 129, 137, 30, 160, 211, 11, 120, 23, 227, 159, 70, 63, 61, 190, 146, 209, 140, 177, 46, + 251, 24, 77, 182, 151, 44, 116, 45, 16, 120, 64, 139, 208, 34, 252, 63, 228, 245, 134, 165, + 99, 73, 251, 30, 250, 72, 186, 55, 150, 113, 30, 26, 180, 243, 21, 75, 197, 232, 86, 16, + 163, 47, 16, 35, 136, 250, 47, 176, 222, 150, 117, 49, 229, 207, 103, 230, 167, 130, 118, + 190, 106, 254, 223, 178, 12, 154, 104, 50, 114, 48, 28, 188, 30, 82, 247, 236, 180, 23, 62, + 171, 236, 178, 185, 202, 27, 194, 216, 119, 36, 54, 142, 35, 185, 149, 203, 233, 18, 131, + 34, 220, 48, 167, 38, 176, 191, 18, 181, 168, 5, 63, 178, 179, 8, 123, 232, 186, 234, 254, + 126, 125, 158, 143, 175, 87, 148, 74, 51, 194, 73, 172, 207, 234, 28, 149, 157, 182, 149, + 144, 15, 70, 78, 23, 51, 122, 83, 190, 15, 208, 181, 70, 122, 152, 126, 56, 83, 244, 10, + 181, 6, 0, 0, ]; assert_eq!(bytes, expected_serialization) diff --git a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs index 5a15586bf1b..41e28882993 100644 --- a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs +++ b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs @@ -1,6 +1,7 @@ use std::collections::{BTreeMap, HashSet}; use std::sync::Arc; +use acir::brillig::{BitSize, IntegerBitSize}; use acir::{ acir_field::GenericFieldElement, brillig::{BinaryFieldOp, HeapArray, MemoryAddress, Opcode as BrilligOpcode, ValueOrArray}, @@ -122,10 +123,20 @@ fn inversion_brillig_oracle_equivalence() { let brillig_bytecode = BrilligBytecode { bytecode: vec![ + BrilligOpcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(2u64), + }, + BrilligOpcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), - size: 2, - offset: 0, + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), }, equal_opcode, // Oracles are named 'foreign calls' in brillig @@ -258,10 +269,20 @@ fn double_inversion_brillig_oracle() { let brillig_bytecode = BrilligBytecode { bytecode: vec![ + BrilligOpcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(3u64), + }, + BrilligOpcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), - size: 3, - offset: 0, + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), }, equal_opcode, // Oracles are named 'foreign calls' in brillig @@ -366,12 +387,21 @@ fn oracle_dependent_execution() { let brillig_bytecode = BrilligBytecode { bytecode: vec![ + BrilligOpcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(3u64), + }, + BrilligOpcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), - size: 3, - offset: 0, - }, - // Oracles are named 'foreign calls' in brillig + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), + }, // Oracles are named 'foreign calls' in brillig BrilligOpcode::ForeignCall { function: "invert".into(), destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(1))], @@ -498,10 +528,20 @@ fn brillig_oracle_predicate() { let brillig_bytecode = BrilligBytecode { bytecode: vec![ + BrilligOpcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(2u64), + }, + BrilligOpcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), - size: 2, - offset: 0, + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), }, equal_opcode, // Oracles are named 'foreign calls' in brillig @@ -607,8 +647,11 @@ fn unsatisfied_opcode_resolved_brillig() { let w_y = Witness(5); let w_result = Witness(6); - let calldata_copy_opcode = - BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), size: 2, offset: 0 }; + let calldata_copy_opcode = BrilligOpcode::CalldataCopy { + destination_address: MemoryAddress(0), + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), + }; let equal_opcode = BrilligOpcode::BinaryFieldOp { op: BinaryFieldOp::Equals, @@ -627,7 +670,23 @@ fn unsatisfied_opcode_resolved_brillig() { let stop_opcode = BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }; let brillig_bytecode = BrilligBytecode { - bytecode: vec![calldata_copy_opcode, equal_opcode, jmp_if_opcode, trap_opcode, stop_opcode], + bytecode: vec![ + BrilligOpcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(2u64), + }, + BrilligOpcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + calldata_copy_opcode, + equal_opcode, + jmp_if_opcode, + trap_opcode, + stop_opcode, + ], }; let opcode_a = Expression { @@ -679,7 +738,7 @@ fn unsatisfied_opcode_resolved_brillig() { ACVMStatus::Failure(OpcodeResolutionError::BrilligFunctionFailed { function_id: BrilligFunctionId(0), payload: None, - call_stack: vec![OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 }] + call_stack: vec![OpcodeLocation::Brillig { acir_index: 0, brillig_index: 5 }] }), "The first opcode is not satisfiable, expected an error indicating this" ); diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index 53597ece157..ba26e3d139a 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,13 +2,14 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `complex_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 77, 90, 199, 17, 102, 55, 39, 24, 152, 57, 64, 199, - 19, 120, 23, 113, 167, 232, 210, 227, 107, 49, 98, 124, 22, 92, 88, 65, 31, 148, 244, 147, 207, 75, 66, 202, 52, 33, - 27, 23, 203, 254, 33, 210, 136, 244, 247, 150, 214, 152, 117, 11, 145, 238, 24, 254, 28, 207, 151, 59, 139, 163, 185, - 1, 71, 123, 2, 71, 82, 253, 191, 96, 191, 99, 246, 37, 106, 253, 108, 96, 126, 18, 154, 230, 43, 149, 243, 83, 100, - 134, 133, 246, 70, 134, 182, 131, 183, 2, 78, 172, 247, 250, 1, 71, 132, 17, 196, 46, 137, 150, 105, 238, 82, 197, - 133, 33, 254, 75, 101, 89, 182, 77, 87, 87, 189, 5, 85, 164, 251, 85, 251, 31, 188, 51, 216, 161, 173, 134, 254, 192, - 66, 186, 28, 208, 219, 243, 253, 166, 165, 196, 115, 217, 7, 253, 216, 100, 109, 69, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 81, 14, 194, 48, 8, 133, 118, 206, 26, 255, 60, 129, 137, 30, 160, 211, + 11, 120, 23, 227, 159, 70, 63, 61, 190, 146, 209, 140, 177, 46, 251, 24, 77, 182, 151, 44, 116, 45, 16, 120, 64, 139, + 208, 34, 252, 63, 228, 245, 134, 165, 99, 73, 251, 30, 250, 72, 186, 55, 150, 113, 30, 26, 180, 243, 21, 75, 197, 232, + 86, 16, 163, 47, 16, 35, 136, 250, 47, 176, 222, 150, 117, 49, 229, 207, 103, 230, 167, 130, 118, 190, 106, 254, 223, + 178, 12, 154, 104, 50, 114, 48, 28, 188, 30, 82, 247, 236, 180, 23, 62, 171, 236, 178, 185, 202, 27, 194, 216, 119, + 36, 54, 142, 35, 185, 149, 203, 233, 18, 131, 34, 220, 48, 167, 38, 176, 191, 18, 181, 168, 5, 63, 178, 179, 8, 123, + 232, 186, 234, 254, 126, 125, 158, 143, 175, 87, 148, 74, 51, 194, 73, 172, 207, 234, 28, 149, 157, 182, 149, 144, 15, + 70, 78, 23, 51, 122, 83, 190, 15, 208, 181, 70, 122, 152, 126, 56, 83, 244, 10, 181, 6, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts index 3500e03776d..498a914cff4 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,10 +2,11 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `simple_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 80, 49, 10, 192, 32, 12, 52, 45, 45, 133, 110, 190, 68, 127, 224, 103, 28, 92, - 28, 68, 124, 191, 130, 9, 4, 137, 46, 122, 16, 46, 119, 7, 33, 9, 168, 142, 175, 21, 96, 255, 32, 147, 230, 32, 207, - 33, 155, 61, 88, 56, 55, 203, 240, 125, 175, 177, 1, 110, 170, 197, 101, 55, 242, 43, 100, 132, 159, 229, 33, 22, 159, - 242, 234, 87, 51, 45, 121, 90, 200, 42, 48, 209, 35, 111, 164, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 49, 10, 128, 48, 12, 108, 196, 138, 224, 230, 75, 226, 15, 252, 140, 131, + 139, 131, 136, 239, 111, 161, 9, 28, 165, 205, 210, 28, 132, 36, 119, 16, 114, 9, 133, 130, 53, 7, 73, 29, 37, 107, + 143, 80, 238, 148, 204, 99, 56, 200, 111, 22, 227, 190, 83, 93, 16, 146, 193, 112, 22, 225, 34, 168, 205, 142, 174, + 241, 218, 206, 179, 121, 49, 188, 109, 57, 84, 191, 159, 255, 122, 63, 235, 199, 189, 190, 197, 237, 13, 45, 1, 20, + 245, 146, 30, 92, 2, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs b/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs index 2054a34d459..ac469cebf87 100644 --- a/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs +++ b/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs @@ -210,8 +210,8 @@ pub enum BrilligOpcode { /// Copies calldata after the offset to the specified address and length CalldataCopy { destination_address: MemoryAddress, - size: usize, - offset: usize, + size_address: MemoryAddress, + offset_address: MemoryAddress, }, /// We don't support dynamic jumps or calls /// See https://github.com/ethereum/aleth/issues/3404 for reasoning diff --git a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs index 5097ecf4707..2c2ab17230f 100644 --- a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs +++ b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs @@ -236,8 +236,10 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { } self.set_program_counter(*destination) } - Opcode::CalldataCopy { destination_address, size, offset } => { - let values: Vec<_> = self.calldata[*offset..(*offset + size)] + Opcode::CalldataCopy { destination_address, size_address, offset_address } => { + let size = self.memory.read(*size_address).to_usize(); + let offset = self.memory.read(*offset_address).to_usize(); + let values: Vec<_> = self.calldata[offset..(offset + size)] .iter() .map(|value| MemoryValue::new_field(*value)) .collect(); @@ -754,24 +756,17 @@ mod tests { #[test] fn add_single_step_smoke() { - let calldata = vec![FieldElement::from(27u128)]; - - // Add opcode to add the value in address `0` and `1` - // and place the output in address `2` - let calldata_copy = Opcode::CalldataCopy { - destination_address: MemoryAddress::from(0), - size: 1, - offset: 0, - }; + let calldata = vec![]; + + let opcodes = [Opcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(27u128), + }]; // Start VM - let opcodes = [calldata_copy]; let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); - // Process a single VM opcode - // - // After processing a single opcode, we should have - // the vm status as finished since there is only one opcode let status = vm.process_opcode(); assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); @@ -786,7 +781,6 @@ mod tests { #[test] fn jmpif_opcode() { let mut calldata: Vec = vec![]; - let mut opcodes = vec![]; let lhs = { calldata.push(2u128.into()); @@ -800,21 +794,35 @@ mod tests { let destination = MemoryAddress::from(calldata.len()); - opcodes.push(Opcode::CalldataCopy { - destination_address: MemoryAddress::from(0), - size: 2, - offset: 0, - }); - - opcodes.push(Opcode::BinaryFieldOp { destination, op: BinaryFieldOp::Equals, lhs, rhs }); - opcodes.push(Opcode::Jump { location: 3 }); - opcodes.push(Opcode::JumpIf { condition: destination, location: 4 }); + let opcodes = vec![ + Opcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(2u64), + }, + Opcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + Opcode::CalldataCopy { + destination_address: MemoryAddress(0), + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), + }, + Opcode::BinaryFieldOp { destination, op: BinaryFieldOp::Equals, lhs, rhs }, + Opcode::Jump { location: 5 }, + Opcode::JumpIf { condition: destination, location: 6 }, + ]; let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -832,48 +840,49 @@ mod tests { fn jmpifnot_opcode() { let calldata: Vec = vec![1u128.into(), 2u128.into()]; - let calldata_copy = Opcode::CalldataCopy { - destination_address: MemoryAddress::from(0), - size: 2, - offset: 0, - }; - - let jump_opcode = Opcode::Jump { location: 3 }; - - let trap_opcode = Opcode::Trap { revert_data: HeapArray::default() }; - - let not_equal_cmp_opcode = Opcode::BinaryFieldOp { - op: BinaryFieldOp::Equals, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(2), - }; - - let jump_if_not_opcode = - Opcode::JumpIfNot { condition: MemoryAddress::from(2), location: 2 }; - - let add_opcode = Opcode::BinaryFieldOp { - op: BinaryFieldOp::Add, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(2), - }; - - let opcodes = [ - calldata_copy, - jump_opcode, - trap_opcode, - not_equal_cmp_opcode, - jump_if_not_opcode, - add_opcode, + let opcodes = vec![ + Opcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(2u64), + }, + Opcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + Opcode::CalldataCopy { + destination_address: MemoryAddress(0), + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), + }, + Opcode::Jump { location: 5 }, + Opcode::Trap { revert_data: HeapArray::default() }, + Opcode::BinaryFieldOp { + op: BinaryFieldOp::Equals, + lhs: MemoryAddress::from(0), + rhs: MemoryAddress::from(1), + destination: MemoryAddress::from(2), + }, + Opcode::JumpIfNot { condition: MemoryAddress::from(2), location: 4 }, + Opcode::BinaryFieldOp { + op: BinaryFieldOp::Add, + lhs: MemoryAddress::from(0), + rhs: MemoryAddress::from(1), + destination: MemoryAddress::from(2), + }, ]; + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); + + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -888,7 +897,7 @@ mod tests { status, VMStatus::Failure { reason: FailureReason::Trap { revert_data_offset: 0, revert_data_size: 0 }, - call_stack: vec![2] + call_stack: vec![4] } ); @@ -903,10 +912,20 @@ mod tests { let calldata: Vec = vec![((2_u128.pow(32)) - 1).into()]; let opcodes = &[ + Opcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(1u64), + }, + Opcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, Opcode::CalldataCopy { - destination_address: MemoryAddress::from(0), - size: 1, - offset: 0, + destination_address: MemoryAddress(0), + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), }, Opcode::Cast { destination: MemoryAddress::from(1), @@ -919,10 +938,12 @@ mod tests { let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); let status = vm.process_opcode(); assert_eq!(status, VMStatus::Finished { return_data_offset: 1, return_data_size: 1 }); @@ -936,22 +957,34 @@ mod tests { fn mov_opcode() { let calldata: Vec = vec![(1u128).into(), (2u128).into(), (3u128).into()]; - let calldata_copy = Opcode::CalldataCopy { - destination_address: MemoryAddress::from(0), - size: 3, - offset: 0, - }; - - let mov_opcode = - Opcode::Mov { destination: MemoryAddress::from(2), source: MemoryAddress::from(0) }; - - let opcodes = &[calldata_copy, mov_opcode]; + let opcodes = &[ + Opcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(3u64), + }, + Opcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + Opcode::CalldataCopy { + destination_address: MemoryAddress(0), + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), + }, + Opcode::Mov { destination: MemoryAddress::from(2), source: MemoryAddress::from(0) }, + ]; let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); let VM { memory, .. } = vm; @@ -968,28 +1001,32 @@ mod tests { let calldata: Vec = vec![(0u128).into(), (1u128).into(), (2u128).into(), (3u128).into()]; - let calldata_copy = Opcode::CalldataCopy { - destination_address: MemoryAddress::from(0), - size: 4, - offset: 0, - }; - - let cast_zero = Opcode::Cast { - destination: MemoryAddress::from(0), - source: MemoryAddress::from(0), - bit_size: BitSize::Integer(IntegerBitSize::U1), - }; - - let cast_one = Opcode::Cast { - destination: MemoryAddress::from(1), - source: MemoryAddress::from(1), - bit_size: BitSize::Integer(IntegerBitSize::U1), - }; - let opcodes = &[ - calldata_copy, - cast_zero, - cast_one, + Opcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(4u64), + }, + Opcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + Opcode::CalldataCopy { + destination_address: MemoryAddress(0), + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), + }, + Opcode::Cast { + destination: MemoryAddress::from(0), + source: MemoryAddress::from(0), + bit_size: BitSize::Integer(IntegerBitSize::U1), + }, + Opcode::Cast { + destination: MemoryAddress::from(1), + source: MemoryAddress::from(1), + bit_size: BitSize::Integer(IntegerBitSize::U1), + }, Opcode::ConditionalMov { destination: MemoryAddress(4), // Sets 3_u128 to memory address 4 source_a: MemoryAddress(2), @@ -1007,16 +1044,16 @@ mod tests { let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); let status = vm.process_opcode(); assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); @@ -1036,11 +1073,23 @@ mod tests { vec![(2u128).into(), (2u128).into(), (0u128).into(), (5u128).into(), (6u128).into()]; let calldata_size = calldata.len(); - let calldata_copy = Opcode::CalldataCopy { - destination_address: MemoryAddress::from(0), - size: 5, - offset: 0, - }; + let calldata_copy_opcodes = vec![ + Opcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(5u64), + }, + Opcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + Opcode::CalldataCopy { + destination_address: MemoryAddress(0), + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), + }, + ]; let cast_opcodes: Vec<_> = (0..calldata_size) .map(|index| Opcode::Cast { @@ -1082,7 +1131,8 @@ mod tests { destination: MemoryAddress::from(2), }; - let opcodes: Vec<_> = std::iter::once(calldata_copy) + let opcodes: Vec<_> = calldata_copy_opcodes + .into_iter() .chain(cast_opcodes) .chain([equal_opcode, not_equal_opcode, less_than_opcode, less_than_equal_opcode]) .collect(); @@ -1091,6 +1141,10 @@ mod tests { // Calldata copy let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::InProgress); for _ in 0..calldata_size { let status = vm.process_opcode(); @@ -1242,7 +1296,7 @@ mod tests { let r_tmp = MemoryAddress::from(3); let r_pointer = MemoryAddress::from(4); - let start: [Opcode; 5] = [ + let start = [ // sum = 0 Opcode::Const { destination: r_sum, value: 0u128.into(), bit_size: BitSize::Field }, // i = 0 @@ -1263,10 +1317,20 @@ mod tests { value: 5u128.into(), bit_size: BitSize::Integer(bit_size), }, + Opcode::Const { + destination: MemoryAddress(100), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(memory.len() as u32), + }, + Opcode::Const { + destination: MemoryAddress(101), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, Opcode::CalldataCopy { destination_address: MemoryAddress(5), - size: memory.len(), - offset: 0, + size_address: MemoryAddress(100), + offset_address: MemoryAddress(101), }, ]; let loop_body = [ @@ -1359,8 +1423,8 @@ mod tests { Opcode::Const { destination: r_pointer, value: 4u128.into(), bit_size }, // call recursive_fn Opcode::Call { - location: 5, // Call after 'start' - }, + location: 5, // Call after 'start' + }, // end program by jumping to end Opcode::Jump { location: 100 }, ]; @@ -1510,10 +1574,20 @@ mod tests { vec![(1u128).into(), (3u128).into(), (2u128).into(), (4u128).into()]; let invert_program = vec![ + Opcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(initial_matrix.len() as u32), + }, + Opcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, Opcode::CalldataCopy { - destination_address: MemoryAddress::from(2), - size: initial_matrix.len(), - offset: 0, + destination_address: MemoryAddress(2), + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), }, // input = 0 Opcode::Const { @@ -1600,10 +1674,20 @@ mod tests { // First call: let string_double_program = vec![ + Opcode::Const { + destination: MemoryAddress(100), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(input_string.len() as u32), + }, + Opcode::Const { + destination: MemoryAddress(101), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, Opcode::CalldataCopy { destination_address: MemoryAddress(4), - size: input_string.len(), - offset: 0, + size_address: MemoryAddress(100), + offset_address: MemoryAddress(101), }, // input_pointer = 4 Opcode::Const { @@ -1698,10 +1782,20 @@ mod tests { vec![(1u128).into(), (3u128).into(), (2u128).into(), (4u128).into()]; let invert_program = vec![ + Opcode::Const { + destination: MemoryAddress(100), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(initial_matrix.len() as u32), + }, + Opcode::Const { + destination: MemoryAddress(101), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, Opcode::CalldataCopy { - destination_address: MemoryAddress::from(2), - size: initial_matrix.len(), - offset: 0, + destination_address: MemoryAddress(2), + size_address: MemoryAddress(100), + offset_address: MemoryAddress(101), }, // input = 0 Opcode::Const { @@ -1797,10 +1891,20 @@ mod tests { vec![(34u128).into(), (37u128).into(), (78u128).into(), (85u128).into()]; let matrix_mul_program = vec![ + Opcode::Const { + destination: MemoryAddress(100), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(matrix_a.len() + matrix_b.len()), + }, + Opcode::Const { + destination: MemoryAddress(101), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, Opcode::CalldataCopy { - destination_address: MemoryAddress::from(3), - size: matrix_a.len() + matrix_b.len(), - offset: 0, + destination_address: MemoryAddress(3), + size_address: MemoryAddress(100), + offset_address: MemoryAddress(101), }, // input = 3 Opcode::Const { @@ -1944,11 +2048,24 @@ mod tests { let r_input = MemoryAddress::from(r_ptr); let r_output = MemoryAddress::from(r_ptr + 1); - let program: Vec<_> = std::iter::once(Opcode::CalldataCopy { - destination_address: MemoryAddress::from(0), - size: memory.len(), - offset: 0, - }) + let program: Vec<_> = vec![ + Opcode::Const { + destination: MemoryAddress(100), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(memory.len()), + }, + Opcode::Const { + destination: MemoryAddress(101), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + Opcode::CalldataCopy { + destination_address: MemoryAddress(0), + size_address: MemoryAddress(100), + offset_address: MemoryAddress(101), + }, + ] + .into_iter() .chain(memory.iter().enumerate().map(|(index, mem_value)| Opcode::Cast { destination: MemoryAddress(index), source: MemoryAddress(index), diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs index c17088a5d8c..faf4242a9ca 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs @@ -1,5 +1,5 @@ use acvm::acir::{ - brillig::{BinaryFieldOp, BitSize, MemoryAddress, Opcode as BrilligOpcode}, + brillig::{BinaryFieldOp, BitSize, IntegerBitSize, MemoryAddress, Opcode as BrilligOpcode}, AcirField, }; @@ -19,11 +19,25 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { let zero_const = MemoryAddress::from(2); let input_is_zero = MemoryAddress::from(3); // Location of the stop opcode - let stop_location = 6; + let stop_location = 8; GeneratedBrillig { byte_code: vec![ - BrilligOpcode::CalldataCopy { destination_address: input, size: 1, offset: 0 }, + BrilligOpcode::Const { + destination: MemoryAddress(20), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: F::from(1_usize), + }, + BrilligOpcode::Const { + destination: MemoryAddress::from(21), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: F::from(0_usize), + }, + BrilligOpcode::CalldataCopy { + destination_address: input, + size_address: MemoryAddress::from(20), + offset_address: MemoryAddress::from(21), + }, // Put value zero in register (2) BrilligOpcode::Const { destination: zero_const, @@ -74,10 +88,20 @@ pub(crate) fn directive_quotient() -> GeneratedBrillig { GeneratedBrillig { byte_code: vec![ + BrilligOpcode::Const { + destination: MemoryAddress::from(10), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: F::from(2_usize), + }, + BrilligOpcode::Const { + destination: MemoryAddress::from(11), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: F::from(0_usize), + }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::from(0), - size: 2, - offset: 0, + size_address: MemoryAddress::from(10), + offset_address: MemoryAddress::from(11), }, // No cast, since calldata is typed as field by default //q = a/b is set into register (2) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs index 5ee00cf6c29..c85940cc1c7 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs @@ -46,6 +46,9 @@ impl BrilligContext { arguments: &[BrilligParameter], return_parameters: &[BrilligParameter], ) { + // We need to allocate the variable for every argument first so any register allocation doesn't mangle the expected order. + let mut argument_variables = self.allocate_function_arguments(arguments); + let calldata_size = Self::flattened_tuple_size(arguments); let return_data_size = Self::flattened_tuple_size(return_parameters); @@ -64,75 +67,45 @@ impl BrilligContext { // Copy calldata self.copy_and_cast_calldata(arguments); - // Allocate the variables for every argument: let mut current_calldata_pointer = Self::calldata_start_offset(); - let mut argument_variables: Vec<_> = arguments - .iter() - .map(|argument| match argument { - BrilligParameter::SingleAddr(bit_size) => { - let single_address = self.allocate_register(); - let var = BrilligVariable::SingleAddr(SingleAddrVariable { - address: single_address, - bit_size: *bit_size, - }); - self.mov_instruction(single_address, MemoryAddress(current_calldata_pointer)); - current_calldata_pointer += 1; - var - } - BrilligParameter::Array(_, _) => { - let pointer_to_the_array_in_calldata = - self.make_usize_constant_instruction(current_calldata_pointer.into()); - let rc_register = self.make_usize_constant_instruction(1_usize.into()); - let flattened_size = Self::flattened_size(argument); - let var = BrilligVariable::BrilligArray(BrilligArray { - pointer: pointer_to_the_array_in_calldata.address, - size: flattened_size, - rc: rc_register.address, - }); - - current_calldata_pointer += flattened_size; - var - } - BrilligParameter::Slice(_, _) => { - let pointer_to_the_array_in_calldata = - self.make_usize_constant_instruction(current_calldata_pointer.into()); - - let flattened_size = Self::flattened_size(argument); - let size_register = self.make_usize_constant_instruction(flattened_size.into()); - let rc_register = self.make_usize_constant_instruction(1_usize.into()); - - let var = BrilligVariable::BrilligVector(BrilligVector { - pointer: pointer_to_the_array_in_calldata.address, - size: size_register.address, - rc: rc_register.address, - }); - - current_calldata_pointer += flattened_size; - var - } - }) - .collect(); - - // Deflatten arrays + // Initialize the variables with the calldata for (argument_variable, argument) in argument_variables.iter_mut().zip(arguments) { match (argument_variable, argument) { + (BrilligVariable::SingleAddr(single_address), BrilligParameter::SingleAddr(_)) => { + self.mov_instruction( + single_address.address, + MemoryAddress(current_calldata_pointer), + ); + current_calldata_pointer += 1; + } ( BrilligVariable::BrilligArray(array), BrilligParameter::Array(item_type, item_count), ) => { + let flattened_size = array.size; + self.usize_const_instruction(array.pointer, current_calldata_pointer.into()); + self.usize_const_instruction(array.rc, 1_usize.into()); + + // Deflatten the array let deflattened_address = self.deflatten_array(item_type, array.size, array.pointer); self.mov_instruction(array.pointer, deflattened_address); array.size = item_type.len() * item_count; self.deallocate_register(deflattened_address); + + current_calldata_pointer += flattened_size; } ( BrilligVariable::BrilligVector(vector), BrilligParameter::Slice(item_type, item_count), ) => { let flattened_size = Self::flattened_size(argument); + self.usize_const_instruction(vector.pointer, current_calldata_pointer.into()); + self.usize_const_instruction(vector.rc, 1_usize.into()); + self.usize_const_instruction(vector.size, flattened_size.into()); + // Deflatten the vector let deflattened_address = self.deflatten_array(item_type, flattened_size, vector.pointer); self.mov_instruction(vector.pointer, deflattened_address); @@ -140,14 +113,45 @@ impl BrilligContext { vector.size, (item_type.len() * item_count).into(), ); - self.deallocate_register(deflattened_address); + + current_calldata_pointer += flattened_size; } - _ => {} + _ => unreachable!("ICE: cannot match variables against arguments"), } } } + fn allocate_function_arguments( + &mut self, + arguments: &[BrilligParameter], + ) -> Vec { + arguments + .iter() + .map(|argument| match argument { + BrilligParameter::SingleAddr(bit_size) => { + BrilligVariable::SingleAddr(SingleAddrVariable { + address: self.allocate_register(), + bit_size: *bit_size, + }) + } + BrilligParameter::Array(_, _) => { + let flattened_size = Self::flattened_size(argument); + BrilligVariable::BrilligArray(BrilligArray { + pointer: self.allocate_register(), + size: flattened_size, + rc: self.allocate_register(), + }) + } + BrilligParameter::Slice(_, _) => BrilligVariable::BrilligVector(BrilligVector { + pointer: self.allocate_register(), + size: self.allocate_register(), + rc: self.allocate_register(), + }), + }) + .collect() + } + fn copy_and_cast_calldata(&mut self, arguments: &[BrilligParameter]) { let calldata_size = Self::flattened_tuple_size(arguments); self.calldata_copy_instruction( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs index afea3f326b0..fab43041e65 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs @@ -394,43 +394,7 @@ impl BrilligContext< constant, bit_size ); - if bit_size > 128 && constant.num_bits() > 128 { - let high = F::from_be_bytes_reduce( - constant.to_be_bytes().get(0..16).expect("FieldElement::to_be_bytes() too short!"), - ); - let low = F::from(constant.to_u128()); - let high_register = SingleAddrVariable::new(self.allocate_register(), 254); - let low_register = SingleAddrVariable::new(self.allocate_register(), 254); - let intermediate_register = SingleAddrVariable::new(self.allocate_register(), 254); - - self.constant(high_register.address, high_register.bit_size, high, false); - self.constant(low_register.address, low_register.bit_size, low, false); - // I want to multiply high by 2^128, but I can't get that big constant in. - // So I'll multiply by 2^64 twice. - self.constant( - intermediate_register.address, - intermediate_register.bit_size, - F::from(1_u128 << 64), - false, - ); - self.binary(high_register, intermediate_register, high_register, BrilligBinaryOp::Mul); - self.binary(high_register, intermediate_register, high_register, BrilligBinaryOp::Mul); - // Now we can add. - self.binary(high_register, low_register, intermediate_register, BrilligBinaryOp::Add); - if indirect { - self.cast( - SingleAddrVariable::new(intermediate_register.address, bit_size), - intermediate_register, - ); - self.store_instruction(result, intermediate_register.address); - } else { - self.cast(SingleAddrVariable::new(result, bit_size), intermediate_register); - } - - self.deallocate_single_addr(high_register); - self.deallocate_single_addr(low_register); - self.deallocate_single_addr(intermediate_register); - } else if indirect { + if indirect { self.push_opcode(BrilligOpcode::IndirectConst { destination_pointer: result, value: constant, @@ -481,11 +445,15 @@ impl BrilligContext< ) { self.debug_show.calldata_copy_instruction(destination, calldata_size, offset); + let size_var = self.make_usize_constant_instruction(calldata_size.into()); + let offset_var = self.make_usize_constant_instruction(offset.into()); self.push_opcode(BrilligOpcode::CalldataCopy { destination_address: destination, - size: calldata_size, - offset, + size_address: size_var.address, + offset_address: offset_var.address, }); + self.deallocate_single_addr(size_var); + self.deallocate_single_addr(offset_var); } pub(super) fn trap_instruction(&mut self, revert_data: HeapArray) { diff --git a/noir/noir-repo/docs/docs/noir/standard_library/meta/function_def.md b/noir/noir-repo/docs/docs/noir/standard_library/meta/function_def.md index 7fae5fc381a..c9fa3b345f0 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/meta/function_def.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/meta/function_def.md @@ -11,7 +11,7 @@ a function definition in the source program. #include_code add_attribute noir_stdlib/src/meta/function_def.nr rust -Adds an attribute to the function. This is only valid +Adds an attribute to the function. This is only valid on functions in the current crate which have not yet been resolved. This means any functions called at compile-time are invalid targets for this method. @@ -19,7 +19,7 @@ This means any functions called at compile-time are invalid targets for this met #include_code body noir_stdlib/src/meta/function_def.nr rust -Returns the body of the function as an expression. This is only valid +Returns the body of the function as an expression. This is only valid on functions in the current crate which have not yet been resolved. This means any functions called at compile-time are invalid targets for this method. @@ -90,8 +90,8 @@ This means any functions called at compile-time are invalid targets for this met #include_code set_return_public noir_stdlib/src/meta/function_def.nr rust -Mutates the function's return visibility to public (if `true` is given) or private (if `false` is given). -This is only valid on functions in the current crate which have not yet been resolved. +Mutates the function's return visibility to public (if `true` is given) or private (if `false` is given). +This is only valid on functions in the current crate which have not yet been resolved. This means any functions called at compile-time are invalid targets for this method. ### set_unconstrained @@ -99,5 +99,5 @@ This means any functions called at compile-time are invalid targets for this met #include_code set_unconstrained noir_stdlib/src/meta/function_def.nr rust Mutates the function to be unconstrained (if `true` is given) or not (if `false` is given). -This is only valid on functions in the current crate which have not yet been resolved. -This means any functions called at compile-time are invalid targets for this method. \ No newline at end of file +This is only valid on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml index 5bdebb476be..3f6bf0b427a 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml @@ -1,575 +1,4 @@ key_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" -proof = [ - "0x0000000000000000000000000000000000000000000000000000000000000040", - "0x0000000000000000000000000000000000000000000000000000000000000011", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", - "0x00000000000000000000000000000000000000000000000b75c020998797da78", - "0x0000000000000000000000000000000000000000000000005a107acb64952eca", - "0x000000000000000000000000000000000000000000000000000031e97a575e9d", - "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", - "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", - "0x00000000000000000000000000000000000000000000000d722669117f9758a4", - "0x000000000000000000000000000000000000000000000000000178cbf4206471", - "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", - "0x000000000000000000000000000000000000000000000007fd51009034b3357f", - "0x000000000000000000000000000000000000000000000009889939f81e9c7402", - "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", - "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", - "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", - "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", - "0x0000000000000000000000000000000000000000000000000001b52c2020d746", - "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", - "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", - "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", - "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", - "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", - "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", - "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", - "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", - "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", - "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", - "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", - "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", - "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", - "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", - "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", - "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", - "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", - "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", - "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", - "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", - "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", - "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", - "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", - "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", - "0x000000000000000000000000000000286fcda0e28617c86e195005b9f2efc555", - "0x00000000000000000000000000000000000dc409eb684b23f6a97175bcb9b486", - "0x000000000000000000000000000000e8de6a193cd36414f598bc7c48d67c3b59", - "0x00000000000000000000000000000000002a8a791544cad8c712de871e3de50a", - "0x000000000000000000000000000000d6f1e64b562df0f17ecc6aa46392f8d5a3", - "0x00000000000000000000000000000000000aac977763f33fd6a360ccc50a827a", - "0x000000000000000000000000000000899fa957f5597c6419e3ead9843d21d917", - "0x000000000000000000000000000000000016c4611846952bd6833c35fb11c0da", - "0x013dbfbfbfb2ae7d524edb15343e551d9510b3116223baaa67312d17652f2fb1", - "0x2f268eb3217ef1ac66016aa14d43033f932335371795b5e6dcb0c87c8ad0d050", - "0x2d5dbd52e00ae837e9868289fbe9057f16ea5b76c7e362603e8883f0de4b3e94", - "0x0e357b6a266c20d5e546c2931475eb044d7e75e08ec31b5e8623aec30f964323", - "0x0a9ace4dea44d0a2e8d12d495a683f508714356656aea3882436b729ead24165", - "0x0c17102a98ccb76faf0f78d669ee9cfb694849896787c985225d92e1af3cab35", - "0x09cc7cb719deb139c84fd9fa273e862a1b5d1cec2501c6cd8ba3c37ca06ac07f", - "0x15a0369f3f95d53687dfe79483baf75597d8b281fe0595caf1f7c9ccf99d985e", - "0x17fb53a42b3d1fa5d26ab19dfcc0d74d1781cee0be98dcc492c22e8f3442c4db", - "0x291d6810fc6afc5c2254fd283843a74c85a77275eee3049ea8ed9c88e02a99b8", - "0x0ad40d1627c31247dfb894584a71f8599cfcb85afe84b20186fc07fccae1aa4a", - "0x251cd908fb4e9fe88660f2303f8d7e4d7886da32fddc0319a842b99543659c0b", - "0x1885bdea3dd82085ca67502ebec8ad87213493e18a06cfa27e2c69810481b4a7", - "0x239ab5ba86866bc6705091f82a6a29444dc76b0e7d94cede7eb745cce36ab2cf", - "0x088d29a03baa491845d152124189dfb8bf70ba9bf1fb00c379199dbb0195c663", - "0x18c9fbe3227988d2da599eba82d60f4de25b442b663585fdc611e37305fa77fc", - "0x010242ae641a8cc4d06b5d24e38d9fa6254f981e28f238ccf6aad580f780d3f5", - "0x00128d34b122e84d7e23276b1f13f5789a562e82c727e9ffcfd7bbaccbe69e04", - "0x0776defaf478bfea4db2698542314e27213f63c96e41f98d4d82a47ed6fab55d", - "0x273014a360eaaa493e398df82f18d9cae37f4b6c0ead20100cad3f5491805298", - "0x2b13528eb9ab6fa705f2b48c9ec6ce054ac984e3adf17d4d73431e8456bf4a3c", - "0x22dafe1d63e39cd2effb236da2e131ee1c8cf4049ce504431dcaf98f75c47ad8", - "0x1afb5bc7eb8d30d807101357bb290f9c3113523f4aacc1154a27b075e46a4fa4", - "0x0782dd7df679163e5f0c126abc901d00f3d7d0856b4c02a199ab691ecd7566e6", - "0x2e556c722c99a84a09ffdcc719178277f8e6c9e31a4769270e3b522b944b8ea2", - "0x1be933a48dca8ef26202d3f135998ac8bed6947020b7447ffb6033b0e37f2065", - "0x2d8ebae210848de2464f5435f1fd4b5467ee938910d7779002614943060bbb32", - "0x2da854bbee38a94a6a9c2c85dd05bb4c879173720b67f93f78b9de93cdb427b0", - "0x0fa2649472af2e79489c466b58002f8f284f953085ac0a98dfabee85b78f63cf", - "0x304a09437636026ef0746c4b8ac1ca0ff250c5630fb5bd03ddafddd7cbde850e", - "0x0c83bb3c6ee0faa1646ee4d8dd83f67ec98e5d63ac802f7bdebfcdf21dee62f1", - "0x229d7e4524b30c18a6b94f0054e6d2ea8eb2396f58f9c808d2c9f991e2be2399", - "0x1265bf5e1aaddeae09242b1435e2f8f9e7487bf76a0461752777f6ea1ff75ad6", - "0x2f32f53281b7a363d6bec84ca21c71c3206d906b036e8b36b0702780e3b1b870", - "0x017fb18c9aef4d6d2bc99f5d7f9a002c8921fcd7c7ba69bf05930b55c2829cb7", - "0x2ec761c02ef6f2eefb7c9b2d6df71795d0ce0820f86797e2e11415cb5b122f22", - "0x2b1722960f42a1b40ffae3e4b9419fc8ff5cb8139a2c7e89af332ba2e95c1b5f", - "0x2dafa15594da2318245475c77eae3712429226b3005852e70f567efff0a7d79a", - "0x2ed44d7e3d5f44ac8f7c144ee0ba9d369c82428827c19b010384708bbc52a3f9", - "0x2777eedda697c7f90aee44fa97cfe62596d16c43fa3545b48d622023ca7a446a", - "0x1a47a5c1b0f41905aa0bad6248be8c7887ddea3ad9dfc8462b23a95b073c8a49", - "0x093656d571e84ac676a265dd509c98513039552b7a24e001b003ca618cc4ea5c", - "0x15c901e8a7ff0f1ae1989b5cfb687975c16716a8014a4052d527d4db4ecbaeb4", - "0x08bfa20e83096b0be58e4c96232510c8ef9824c0a62b91ffcc4592b217753a72", - "0x021913efbdfbc73aa5f4a97c79f352ac61f71248947f5eb5713c1b107c632703", - "0x00df89625aef270fab2a8c33ba742e1375423f4cfb3f63514ae748e004bb8cf4", - "0x2455f76c8ee59e93cbe7fe192cf0f766e1399617cabfa230cf27ca2a18cd58d5", - "0x150c3e56ea4f6442ed6b11030c98682a8f5e3c9cd6fd18949254a7c79b3cb5b6", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x01e89c6fe644aea7f63301278dbdb4ea29cf4d33f8b0cdcd79cb106e0bf0a753", - "0x2d49d23421e253903b8a5d0911642b9ce218cef4e350cf8689704eb1f3ae38d4", - "0x072956ca447343d788791fee1ef222f280048ad4aefb6cb7bc96b538f482f525", - "0x168176bf15c8ca63457acf05efbe54af452ea41f935ab82c2a96fedde10ba52f", - "0x20a13690f13491f7f3b756a1dc3b69a3f96d78355c70289583032a593bfc87bc", - "0x273e0a32ab3ef0d3f179b62520b31015ccfc8b53c76a1bb323b41e40ff954596", - "0x28019d4b05546b44e35d5dc74375b75dabb6fae49a07381605c60423c6163d26", - "0x10beda0b8dd484c63f0937820e2c7e9be832a0031efe3557631608895255ca5f", - "0x095a8f04a901526e4d70b1560bfff29b5a3c30347725d1e420c1b30ee2bf8a1c", - "0x1fb742e863a5c76262ffec93b3351405b0840b326fa5fffd73f40abcd5f05f05", - "0x11fa63cfcb2e603fe4e4668d75f05a2cf22650b84a91d1753e83f0e7ae83b4ad", - "0x2872e3d3c431a8b7ee4cec1c2a999a42c40ae33382fbba80a6d4c1a39b2d57a3", - "0x17e8c2a5f809f9935d7c6d7cb2f8859a513864b53f53de3d2a14c74cd690bd1a", - "0x20a552298d691393ae401382b3015689231ad988d3eb0521d414dcd2e8781053", - "0x183eb6bca59a141b4e8136179a258272ec9c25ec80bdb0458b6880c711707a28", - "0x03cd147a2a4c8dc272f3e240b8b0090d45e994e5fd40e07a54f6765795cd5ef8", - "0x082b135b3a20da4c766242b4258e27dbc050e4b8958bb15431626f2eeed9bd2b", - "0x28c894a6a719a32fe8d78ded46bc685ba035e5579c88fbc5bcbc0f09d8c5268b", - "0x06418cceff50837f923e63a37c2c534d13d9f59793c3aa6274813baa64d1899e", - "0x2b4a27b672f85c4fc697605da213de8b950a629602c5b8c6403e6c1c1065388a", - "0x0e2b817c6a79d6d1027f0376fb26ec81a140a4402e2dcdff6152cf01f2f4dbf9", - "0x2ae0fbce87dc53f0ff5473117e1c49a8197a14f8eaaec00cb5b10f94e844111f", - "0x2368004a1dee06f505e75ada3e9f8cc4c801f6a2068620da51ba11f537453835", - "0x2009df8e6f49f67dcaecb93e4a9ef81aaff096136d26f0fe691e14cd580c47da", - "0x2e512617136e8da2817856e57f13087a75fcc512faefc6d4b2eedd73c58a9b35", - "0x2848fcd535bd7c8017ca331a14919aa492ed05b04e9d0745480d291205eac8dc", - "0x19bb0990cb37f3a8f6c3db78219b07d6accd08e889586660e92dd6000755f09a", - "0x15520c8158b2e36c40c5fa46d5281c45d3df2c7f5d974a1f9549bfca6cbceaea", - "0x0e285f4df658d99922c286c5a253d6f6f37aa6c52d7a0fc1a20f3e6da9df23e1", - "0x0f9cd4667f4c1e86f83eda9e752a05c0cc630b0827a93a68322fa258dffb0f24", - "0x12d8b0dbbea3dccfe5d2dd090daf8ab4d2fac74fada9c49875b0c9122663a8ad", - "0x2e8c814d93f027ecff08c4e58555aadfc0f9ec3889eff2150f2b5bb6c557add0", - "0x013516a1456c5831aba87e4057878f6f3f18471e0674fd1e89be3e18351ec394", - "0x14418aa79dc84fd791d5638bdc103786ef8181a714ee8e022d3a1e792cbc7959", - "0x14418aa79dc84fd791d5638bdc103786ef8181a714ee8e022d3a1e792cbc7959", - "0x25c5e6c96a39bb36e19106d4049b675f0279084cc757c4e2acf6e497c61056a2", - "0x231aaafcf2a4c6fd8da18ce5ae5b33790f2c306a2692c6383c9a0787c50ac269", - "0x0a5f7665f0997081f9b38ec64e9a18542ac3a9648060f8cc720fc04669224730", - "0x0f1c9d9d1ac6f62825c6038117ed30540be434e8fd2d88150dcd4fece39b335a", - "0x1308871c8fcb09f07e5257f5cc5678d98842a8d18b2af09b5132d9af3cb1893e", - "0x28801985290dac4eba72ed01ee06fe88f6fc533dc1a46bd86e2d35be8021b042", - "0x14407f38cfba3cc61fca173b41133ab05a1c176caf8bb597588b01817e9eeaa3", - "0x0ea1a9f6f95f6193e512a7bd3db0c147f66687662934aed53cb657935b1e4eb9", - "0x1bc4ab6eacd61b5fd9e414b0186ef5deaadaf59aa9e53cb8d8812255baa28109", - "0x00000000000000000000000000000093a4da68a2fac0ee94841efdfc57eb748c", - "0x00000000000000000000000000000000001c22f1f5f927bee6adb649cc132391", - "0x0000000000000000000000000000003d0c2acea76c551f58876b3c35f19f345a", - "0x00000000000000000000000000000000002e94fded0a0b7f4fd1c882fd2a4e52", - "0x00000000000000000000000000000022e23b6fa0f72844bf8f60ea140cca5663", - "0x000000000000000000000000000000000013380f284bf3cb98b9a7cbae7d702b", - "0x000000000000000000000000000000942a13cf93056815c3f7439c9eed0a103e", - "0x00000000000000000000000000000000002be14bec02c6dae4625d32866de4fc", - "0x000000000000000000000000000000e2a2c75dc664c12695b4f7795c61f92669", - "0x000000000000000000000000000000000000725da448f376bde6cf63bcf79463", - "0x000000000000000000000000000000f54eee585f8ab367dc66a587e1d4cdbd8c", - "0x0000000000000000000000000000000000071106624ae5623a070f0addc18433", - "0x000000000000000000000000000000d60352bea3b2adb311b1a3beb25acb8aed", - "0x00000000000000000000000000000000001965b7c781e33f94e90c743c7881ed", - "0x0000000000000000000000000000006458a2aa57539e2b192f9c3ed69f9fb674", - "0x00000000000000000000000000000000001fc9c667723a4e66d752c6b426d444", - "0x0000000000000000000000000000008d1ff1c5d59a463c5b46bcf52f41ad3c63", - "0x00000000000000000000000000000000001b3e73df070a35c49a03fab1c76e9b", - "0x0000000000000000000000000000001c17a62b6c0a7ab14de83391e06f780adb", - "0x000000000000000000000000000000000012c7fbe2591b9ae72dd526e4ed1d7f", - "0x000000000000000000000000000000a758fa0c72d6a93155cb18b3fcc7defd34", - "0x00000000000000000000000000000000000cea12961770ce7cb6f2a4aed009fe", - "0x000000000000000000000000000000ef6e9647803aac315fa6d287e0e66f4767", - "0x0000000000000000000000000000000000259a82b8d6c6015cc51d2681f26ad4", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000008152b373c87004bef7d2c55ec8c540b67f", - "0x00000000000000000000000000000000000a55be5fdcb0a0dce4976d7bb78b0c", - "0x000000000000000000000000000000f749ea03f04ac964706139b9d1db595ecb", - "0x000000000000000000000000000000000013218e14dae80c066b4e46e9309fb2", - "0x0000000000000000000000000000004bbd7f950c36ce69db39e2b234a9e3f9b0", - "0x00000000000000000000000000000000002a0c3994d892ca5ea26984abbb30fb", - "0x0000000000000000000000000000006c1b39306846620bd546ac2c897834f259", - "0x000000000000000000000000000000000020350b9f507d6e25961a11be3e494b", -] -public_inputs = [ - "0x0000000000000000000000000000000000000000000000000000000000000003", -] -verification_key = [ - "0x0000000000000000000000000000000000000000000000000000000000000040", - "0x0000000000000000000000000000000000000000000000000000000000000011", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000003", - "0x0000000000000000000000000000000000000000000000000000000000000004", - "0x0000000000000000000000000000000000000000000000000000000000000005", - "0x0000000000000000000000000000000000000000000000000000000000000006", - "0x0000000000000000000000000000000000000000000000000000000000000007", - "0x0000000000000000000000000000000000000000000000000000000000000008", - "0x0000000000000000000000000000000000000000000000000000000000000009", - "0x000000000000000000000000000000000000000000000000000000000000000a", - "0x000000000000000000000000000000000000000000000000000000000000000b", - "0x000000000000000000000000000000000000000000000000000000000000000c", - "0x000000000000000000000000000000000000000000000000000000000000000d", - "0x000000000000000000000000000000000000000000000000000000000000000e", - "0x000000000000000000000000000000000000000000000000000000000000000f", - "0x0000000000000000000000000000000000000000000000000000000000000010", - "0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84", - "0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae", - "0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16", - "0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1", - "0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c", - "0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7", - "0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8", - "0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c", - "0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5", - "0x00000000000000000000000000000000002002681bb417184b2df070a16a3858", - "0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511", - "0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223", - "0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7", - "0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c", - "0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130", - "0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f", - "0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3", - "0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592", - "0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3", - "0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1", - "0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0", - "0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c", - "0x0000000000000000000000000000009f825dde88092070747180d581c342444a", - "0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01", - "0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff", - "0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9", - "0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1", - "0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b", - "0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2", - "0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f", - "0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0", - "0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349", - "0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8", - "0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2", - "0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556", - "0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d", - "0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb", - "0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d", - "0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8", - "0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862", - "0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e", - "0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830", - "0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f", - "0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe", - "0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb", - "0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56", - "0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc", - "0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4", - "0x00000000000000000000000000000029a17181c7934fc3fdbd352eac5cb521b9", - "0x00000000000000000000000000000000001f497cbf5284ff29a2d336e5991999", - "0x000000000000000000000000000000072bd9c0c6beda1fdee6d4ff0432ba9e1b", - "0x000000000000000000000000000000000013ea38a0bd2aa751a490a724fac818", - "0x000000000000000000000000000000c599f63dcd3edd49f08ae5c3141c1e3493", - "0x00000000000000000000000000000000002bdb36be0bea09950dd32a8ccf6fbc", - "0x00000000000000000000000000000047f27f29724e7f19eba0340256a0bd4b7d", - "0x00000000000000000000000000000000001c1c5ccf87a962129ca785f8f35120", - "0x000000000000000000000000000000c5c71efdae00679bbe4a95096e012b1817", - "0x000000000000000000000000000000000017a365de041e317817d0135f2b48e0", - "0x0000000000000000000000000000008ae711ac402f7848d719c93a89ba8d39f1", - "0x00000000000000000000000000000000002b6fb40ed8a1935226f4f9786a0499", - "0x0000000000000000000000000000002f03a71501d83de1da5715a4e9462d6198", - "0x00000000000000000000000000000000001644064443b8546f48eae693af47b8", - "0x00000000000000000000000000000083763ab1b6e8fe269b2fe4c7b9c448c08d", - "0x000000000000000000000000000000000021d7cc18c59676a8eeb47c0111c251", - "0x000000000000000000000000000000b5f937153073e03ea7d51a996e0ebc2e6b", - "0x000000000000000000000000000000000011ddd0e26457373eb06e0493177672", - "0x000000000000000000000000000000c5f6eb9f6fc8fa99811a4a88c74a6d018b", - "0x000000000000000000000000000000000025bcd07a0732c123567834f5109558", - "0x000000000000000000000000000000aeb08a0b1a4442189448b4e97490568146", - "0x000000000000000000000000000000000002a1744e4771705536a88f07e0f90f", - "0x000000000000000000000000000000b938568293bd0724b0ea76c2ec34c4a829", - "0x0000000000000000000000000000000000053296e8f3b9ad3af877dfa9c7c2a7", - "0x000000000000000000000000000000f0ca1db6323996eba26bdc86dafef9d10b", - "0x00000000000000000000000000000000001441a46c58af03d5645d52721d956a", - "0x0000000000000000000000000000008bbf8f884013c66c28ba09c2fbd573b656", - "0x0000000000000000000000000000000000206c391ca06fac27d1908e94570243", - "0x0000000000000000000000000000002d4f5aaed88ba4f79612d53b804ca8f194", - "0x00000000000000000000000000000000001674011c96392df08970fa6b7b4cb8", - "0x0000000000000000000000000000009f88297c1729d76c4d9306853598c91325", - "0x0000000000000000000000000000000000256f51adfcacc3c1e340be4d32d3e9", - "0x0000000000000000000000000000000ab9955eec0d74eb799afed2a802b24d75", - "0x00000000000000000000000000000000001fcbe43ea105b30d36ed0b21b03411", - "0x000000000000000000000000000000d66b1d5433f1aa5305cd1edce7c22de466", - "0x00000000000000000000000000000000002331546a256b8a3b751956806680d4", - "0x000000000000000000000000000000e97954ad6cd6f45fb15c91434121db4304", - "0x00000000000000000000000000000000002e20a97e09d50f227ced47e7a98250", - "0x0000000000000000000000000000001ebbc27eb9ebededefba79522eb58ae89b", - "0x0000000000000000000000000000000000090efa4974e566e81d1177b85a30be", - "0x0000000000000000000000000000005eafa070b9c9632404052642e3bc14f9fd", - "0x00000000000000000000000000000000001489068864102daca6a6b8bc4d448b", - "0x0000000000000000000000000000009ebc91aaaac036a6477cadbe54e8556dfd", - "0x00000000000000000000000000000000000ef6d835e2ed3343b95c82c8c54037", - "0x00000000000000000000000000000033b28b529dff46e93af4e7422530478e4a", - "0x000000000000000000000000000000000020a86c2f8591bf190bcddcc03c42fb", - "0x000000000000000000000000000000a9679d0acc088f7dc27bf6d866bcd2dda2", - "0x00000000000000000000000000000000002fb9d0d2d4099402bed74f738f64cc", - "0x00000000000000000000000000000023b09f876a29a061582848a8b9a5870c12", - "0x00000000000000000000000000000000001d5bb906f03f0d49e9c4791bc43af9", - "0x00000000000000000000000000000017aac9854ea240d8ec97bf760c4d4ba870", - "0x00000000000000000000000000000000000b227a556c414ada0dc75bb303e30e", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000009b624fa65d1a24b7f14a8f25f3789622af", - "0x000000000000000000000000000000000013d47bff8c630e847b70e2732fd3f0", - "0x00000000000000000000000000000061d21663e93132f32921075f4c936a84df", - "0x00000000000000000000000000000000001a74ca4e118fb480b9b999902989a3", -] +proof = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", "0x00000000000000000000000000000052eebbd1f6f7554e837f60c44000ed14b6", "0x00000000000000000000000000000000001c1c045a3ec94b8801f2272cc0b3f4", "0x0000000000000000000000000000004d2ef74134578f6b431a9df071ffca4292", "0x0000000000000000000000000000000000291326ade7aa6f0dfc8900eab5580b", "0x0000000000000000000000000000002433eec6418a6dba820c9527e2581fc8bc", "0x00000000000000000000000000000000000e88b7daad19af2ac2f9bdf9e50ee2", "0x000000000000000000000000000000dcfce2c427155cc3e4d035735d3dd5ece8", "0x00000000000000000000000000000000002d7d473cac1a15d0fee8b22c1a7b3e", "0x23fb9503f571d567261006e2ca8b4326d325820140b488bb71617583602f4e3e", "0x0c68b96eebbfcac292403ed3b6f61536550e66473904e7d5d28080108fd0b1c3", "0x08d3bdbefd6d437c50fb9e3e3861913433e76577a18d81aa0ea4b8843e55f9ae", "0x08f6173fe87b72da6d821a496eb99b0cfe0ccadcffd25e5a3b718d83ff9adb1a", "0x1e6bd0a24c2cc58c93cf255cc68dd0c57299c99fd934267906b34facb0145cf4", "0x1175996557630bc376d38636f72b277cb8d54a969a39988a7e78f464c03eaeda", "0x03c3bd1f43baf44de0d9bf0f474c5df04b182214d57a196a717aef8868f9948c", "0x27306ffc7a96c8c27c9812d9dfa649ab6897b69125939aabe814e07d105daa32", "0x0c7f0b70aa08158e55bb39471609782656793ac76a03f2b64dcd135e6542592c", "0x03885b9eff8dac38a64779e3aba31f18c74166892cef9c5081ab57f6daf59865", "0x18dd8385333838c514fd11f36469c88e7ea5f6440aee17fa93c0f03c765d4ced", "0x08ad5bc6c05ecc9ae0d8f0b3196f229a53dbe753f41c12c52045c40e7d8220cc", "0x2f308380f90378084075f2bafa73228b17cbdfc2d693f9aaa1e5089557d0f32e", "0x2d3407e6de05e5935a31037c3db88069d0c41ec86cc8dda815048d6ce76f7a5f", "0x108c231f660e75f209201507a2dba6fccf99734ad91db8ecea675275afdf3ce1", "0x0e68df40e8c467a617229ab0f1dc0d4a04254492e709333d623c0963518dd6b4", "0x290650614292eec7c4f26fd402a047298f1a618dc8ff7de615752f737df7d515", "0x0de290891aaf146fd890a3cd5c25025113df2ec4d0a134513a2f397eaf4e3ea9", "0x25521f6f658bd20d9aaa8041164509b7b8d96fc5ef385f6eb6582375d1a86168", "0x0e9ab2f2f06220644c41fb09456d91751c522b015622f30568e66457f647a2bc", "0x28364f88f1e9c7d8e7767a3b954c5daa29223d646279930b34da51351dc01992", "0x0560c214728aacc262eeee0037be142d81aec26a1f5a9cf0606c4236ed344aa8", "0x1faea1662601fa01ad93d160277a1c81f2c60a761b74660f24a596ec8cb783e7", "0x0e703bb7bbf3a8bb8211715d86a1becb7aa3271f51d6001d5d3042faa7465df9", "0x0cc5b499ea9d9cbae4a0e33a5b601a7f7b686d6980dc0dd5bae4382a8ab1c7c7", "0x27fae143a80a37af95a47d5953096eef9b1127b5475480b8a6ecebdb00a65e23", "0x02cdf7c51d9182fbe07e7768ed0fcfe452ef70fc2ac87dc38fc0d4137bdf4aec", "0x14838df5a54d57d0a28b0375107bb7e7e7259c576a08ea39db6af8b0341d2911", "0x1b1fb0b1242e17beebb218c4ec88c830accea9bc93deec6d087d36d4d8de31fd", "0x1a8c0bdf35e674aa37118f5ad7fe6b62c65d8502e9697b3a92dfda8a1923d110", "0x2819aaa537cf012ceb48a8c8036b6fee492eeeef6698dcf8e3bc825d71efa3f8", "0x1ceedf534535a0d2a427b2ceeb3c8878a658b80eaf5210dbc0d32888fe3d05a7", "0x25c96dba803387eb5f3562785bc3bccddb7c9eb019bd4b07dd4563f77965c00c", "0x0353f3ff0f4f3da362b11eac12167dcbc9b3c76fb555f7e5534c14bb4c3f8037", "0x2904e33424ad29d38bda66a50b54a67acdf09be06a068ddc09d5eabdf9c2a9e5", "0x0b28534bf4b58e7f46c4a7514f3b521dd47bbac2a3adf09387baf19ec8df39c5", "0x1628b67c5d7b8c4cb5d8cdd2d0fd1d92bea3bfcf490fba7f16447cb686d7a388", "0x151bde642447aaf993e737329a3b81c6e243eecbe6a7bb43cdb8ffe74b2c0484", "0x07b319f585e9a9a3883deaddd9b0f43c844cbc7477636034f1543ce9f98821bf", "0x2c8738d76925012cc029f5b888be3cae165daa6beb22b5d73f017c918d891c34", "0x118fff7a26b04a6476c21267a3a4e96247640f6eabd05a05f1a94f881c6ee32b", "0x081d82e0808b6d444b03e1d722375adef2659d5914faa3d9ca4cb12c912be257", "0x18426c5ff5a3140f19bdc05e247cc05e1f70e1ea482b2a2b21f4930a494d7a61", "0x296babb7c6a72783d92bc3dee7f90a97302d64a518faeec0f42af4f599ccc0d1", "0x03337dd83835a2e9fe02c97056360eec725d55b01f039663108939f0333dba11", "0x11a796e7e6f1081be5aad42b475dc224f9547769bc6b358af63207fe0d324a4a", "0x2419618a28070cb7af904460207371f5ff9fa0939f6a0148add60ede530b0f14", "0x004d323457b070f3f41a4ce1ad5a867b3dea1a592bccb40c4d69c8521d9682b6", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x2d6ba30a2a23364900cf52019e2d19574813fe4922763a4e281c58c400ffce14", "0x06a0c085375f88283bedf3a1fc76ef35490655f372e2a985842a9375383b69d7", "0x219b78e5cf2ab2e35edfc8e40362062081a24ff4e9c9d15afa254c2a02d6d4e2", "0x182f29b047e6167c338c36d31685a825c66f327336545c623e7a6bd18e4fa97f", "0x1686460e2586e702724b9daf02315a33ddf5cbd275cfadbc3858f9ef3fe97133", "0x2183aaf585ac708b4000a5b88cf5a767356677087133bd90fff1c3e030b91f1e", "0x27dfa9c69d03c7776fecac8e0f56162caa95f44692cdae91f5b52dfc97eb9006", "0x10a9959de8c6d238c6c6dd68274cc9fc5b6d66759938638072d71659a2fe210d", "0x0e179d6215630fdd7d50362ade21893456d4b9a693e96152d9a6bac6518d4605", "0x0175b579d4e3b24eb0a319a6c79756c8a68ce2c1e0d0d8d1593d685125fbfb66", "0x1132bd3d531944f5024f2705d39b13e00ae90c246f6550c745234fd3d080712b", "0x1f2326f3955b431f2a17e937128b890aa366b107b69c61b8b45832fd06ce9e4e", "0x13576e6c03c3f2042c56113991821ec1f9dec46b6b0ff2748e037c94e6656c40", "0x00bb713034ce9d247110149e2a1754dc76f3ad700d420508148060091037477a", "0x25fb93286a48dc64c67ffac9e3f4a96b6c70bb87744e10e44a782117f8f537a0", "0x191227cd5e49d8a6b5aca93888b3286b41069df547e4bd91ffe65e48ab45b2a8", "0x120d4ac764ca4db67357140c8a8dd1523c013f747250a03a6130416669b087e1", "0x131cc1285b242d73eee36b79ccb3024525ae3caf0f91981cb89ec8d81b16a198", "0x0cacfa5aa1bc4624d5d476aced4d4c8026fb881679172dbc482d18772bc28c9f", "0x0e138279e8a4fe06018e9b9e649921500766e7a7afcc971f41732aa51ec31a43", "0x000000000000000000000000000000332f935a88cd2cc8a138d5ff2efe4cdec8", "0x0e1c2af7515e65c7ebced1a37faf4dbeef5c414f5601219d00d3844658b05a61", "0x12aff8e8eed2d2946c91652d448240590690672893b4759cdd31e1ec9ea45138", "0x1e89f396af25e81f9c4b3af2b0a15fd961789f3a8aa60edbdc4e8f2dfb610375", "0x29c05199f808bf38009ee7fa3c82b6aa5e3d65f180f49d4564c4bf6918399461", "0x019ce7ac46f4e5f1d4ce2d3866321506cea78ff5e5fe400d83b0395341cfe5d5", "0x20b40d1a69e62e7eecbf490915e2791975d3bca30859f237c56c4486e1fbb441", "0x243f7e62233a1f80ee17978814d7ab095bcc416d6bcee4583ce1167c7206b7b4", "0x0b6067a921e8d87bc8fd1af67382fbe2a27bcc833effa13fd7d85b5458d71e28", "0x30307a6766be04f3c50378d1b83f2e147e2ceef344d0c60e1abf939d29c26e27", "0x004c0ec19588b920084d00c6bfe0af4dbf83ca101eac5d833cb8191fe1c298b4", "0x00da79a40286bd8d3993b331a72f8195c7ba04bd863d1afd469bb094e29cc7d9", "0x115b70a2c50ee9abc28472ba8e820cfba158113a5a39c8e31817c84182d0503a", "0x09341d5c4b6d85bde38834a418a8ca375592c320c669bdd540c7ccee760f2ea1", "0x09341d5c4b6d85bde38834a418a8ca375592c320c669bdd540c7ccee760f2ea1", "0x0e63e927a9562ce0914fcd8892dff9a94ac722365ce21b8f5c75cc560b364e57", "0x05cf84989894e741a3e1cd815a8f84febfb08e61ee7b424c902fb02ca7d12e95", "0x1f958ad88d5e4a270f35e534154e7a519c5bbfab36d5084202d5b78baf63e09e", "0x21f0a33450db8821c2f8d042aae7e70bf05c9814b063e73c5e95f8ddba515a81", "0x2767a30fa0351c7deb2c8f542ecace4c41c1d136dd460dfad50b372f2a5f4b71", "0x137ee4ebfbc7227bf57ffc35d3368dd4f96c62911db9380aafa220d061c3b59d", "0x111515d3566611192f64e1e0848635ca6d7f73d8039d8b3522da1e2359e6d1b2", "0x2f6284e905c491b8defe4c467b2e664e2fbf144b5ca45e05c4a9d1aa8d41e149", "0x1e688ca09721459cd96d6af042716567a8f5fdb479f08ff9eff248c6013315a4", "0x00000000000000000000000000000015207c89ecabf752a46c0d5b8dbd296d86", "0x0000000000000000000000000000000000286c2b4d49249737816da8fd9f2753", "0x0000000000000000000000000000002492e649af820ca5d83e59823126c03bfb", "0x00000000000000000000000000000000001cdf1b636e33bf02a813687147476e", "0x000000000000000000000000000000b49023689f96212b8166d0c9b105e6df9a", "0x00000000000000000000000000000000000d9d27730e57d86079464ecd8d9edd", "0x0000000000000000000000000000005292b5583bd716a723bae47d344d655528", "0x000000000000000000000000000000000026651dba1a1074382c734163ab3614", "0x0000000000000000000000000000008984f01bc1f237c72fd6d2bb10cc21eb85", "0x00000000000000000000000000000000001029818de60ae9bb21ac2b5d5a4c97", "0x0000000000000000000000000000003aca28da52679f34e33756dfe00f1d8072", "0x0000000000000000000000000000000000124ecac53af720c02d18f54fd29100", "0x000000000000000000000000000000d09ed1c104d0397f046d89b8476f47e641", "0x00000000000000000000000000000000002c5094b27ad41c8a203b16dc74ee54", "0x000000000000000000000000000000bf8609068d29793771eb3f64e7dc3db96d", "0x0000000000000000000000000000000000225e220e16aedaecf2c10de6e41042", "0x0000000000000000000000000000006ae4f0d8baca7866ad4632141f90770cd7", "0x0000000000000000000000000000000000256cb979ab5bbe98be3a413ae8f246", "0x000000000000000000000000000000891f30bd3ac8e7e63e00db4951d518822f", "0x000000000000000000000000000000000014dffca5d842acfcd23fa491a7dae2", "0x000000000000000000000000000000af99905ea5b7a25f2172f044a59b90e67d", "0x00000000000000000000000000000000001e35bb78e382a5b98ad04b846df528", "0x0000000000000000000000000000003cfb75469b791ea188b8dfdff0f269e7b5", "0x00000000000000000000000000000000000e4fb9eb44a3d44d808794066f8811", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000c42f38f2993af03e18e76996c49f945c6a", "0x00000000000000000000000000000000002aefe820f0e4700abedd9fb6f046c1", "0x0000000000000000000000000000007a878e53414bf22854877c5066eaf916b8", "0x00000000000000000000000000000000001410a75247434da28c1ba6b64703bb", "0x000000000000000000000000000000bca902c1e2af8b47771e7eb42c3870f46b", "0x0000000000000000000000000000000000276eb602c3c232b51668d229d602b8", "0x000000000000000000000000000000dac1254c0753ee39d49d795bc6b3550ba7", "0x000000000000000000000000000000000007d60be9174146bd83f202aa062b92"] +public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x0000000000000000000000000000000000000000000000000000000000000005", "0x0000000000000000000000000000000000000000000000000000000000000006", "0x0000000000000000000000000000000000000000000000000000000000000007", "0x0000000000000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000009", "0x000000000000000000000000000000000000000000000000000000000000000a", "0x000000000000000000000000000000000000000000000000000000000000000b", "0x000000000000000000000000000000000000000000000000000000000000000c", "0x000000000000000000000000000000000000000000000000000000000000000d", "0x000000000000000000000000000000000000000000000000000000000000000e", "0x000000000000000000000000000000000000000000000000000000000000000f", "0x0000000000000000000000000000000000000000000000000000000000000010", "0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84", "0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae", "0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16", "0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1", "0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c", "0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7", "0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8", "0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c", "0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5", "0x00000000000000000000000000000000002002681bb417184b2df070a16a3858", "0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511", "0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223", "0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7", "0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c", "0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130", "0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f", "0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3", "0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592", "0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3", "0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1", "0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0", "0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c", "0x0000000000000000000000000000009f825dde88092070747180d581c342444a", "0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01", "0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff", "0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9", "0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1", "0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b", "0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2", "0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f", "0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0", "0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349", "0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8", "0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2", "0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556", "0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d", "0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb", "0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d", "0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8", "0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862", "0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e", "0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830", "0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f", "0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe", "0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb", "0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56", "0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc", "0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4", "0x00000000000000000000000000000029a17181c7934fc3fdbd352eac5cb521b9", "0x00000000000000000000000000000000001f497cbf5284ff29a2d336e5991999", "0x000000000000000000000000000000072bd9c0c6beda1fdee6d4ff0432ba9e1b", "0x000000000000000000000000000000000013ea38a0bd2aa751a490a724fac818", "0x000000000000000000000000000000c599f63dcd3edd49f08ae5c3141c1e3493", "0x00000000000000000000000000000000002bdb36be0bea09950dd32a8ccf6fbc", "0x00000000000000000000000000000047f27f29724e7f19eba0340256a0bd4b7d", "0x00000000000000000000000000000000001c1c5ccf87a962129ca785f8f35120", "0x000000000000000000000000000000c5c71efdae00679bbe4a95096e012b1817", "0x000000000000000000000000000000000017a365de041e317817d0135f2b48e0", "0x0000000000000000000000000000008ae711ac402f7848d719c93a89ba8d39f1", "0x00000000000000000000000000000000002b6fb40ed8a1935226f4f9786a0499", "0x0000000000000000000000000000002f03a71501d83de1da5715a4e9462d6198", "0x00000000000000000000000000000000001644064443b8546f48eae693af47b8", "0x00000000000000000000000000000083763ab1b6e8fe269b2fe4c7b9c448c08d", "0x000000000000000000000000000000000021d7cc18c59676a8eeb47c0111c251", "0x000000000000000000000000000000b5f937153073e03ea7d51a996e0ebc2e6b", "0x000000000000000000000000000000000011ddd0e26457373eb06e0493177672", "0x000000000000000000000000000000c5f6eb9f6fc8fa99811a4a88c74a6d018b", "0x000000000000000000000000000000000025bcd07a0732c123567834f5109558", "0x000000000000000000000000000000aeb08a0b1a4442189448b4e97490568146", "0x000000000000000000000000000000000002a1744e4771705536a88f07e0f90f", "0x000000000000000000000000000000b938568293bd0724b0ea76c2ec34c4a829", "0x0000000000000000000000000000000000053296e8f3b9ad3af877dfa9c7c2a7", "0x000000000000000000000000000000f0ca1db6323996eba26bdc86dafef9d10b", "0x00000000000000000000000000000000001441a46c58af03d5645d52721d956a", "0x0000000000000000000000000000008bbf8f884013c66c28ba09c2fbd573b656", "0x0000000000000000000000000000000000206c391ca06fac27d1908e94570243", "0x0000000000000000000000000000002d4f5aaed88ba4f79612d53b804ca8f194", "0x00000000000000000000000000000000001674011c96392df08970fa6b7b4cb8", "0x0000000000000000000000000000009f88297c1729d76c4d9306853598c91325", "0x0000000000000000000000000000000000256f51adfcacc3c1e340be4d32d3e9", "0x0000000000000000000000000000000ab9955eec0d74eb799afed2a802b24d75", "0x00000000000000000000000000000000001fcbe43ea105b30d36ed0b21b03411", "0x000000000000000000000000000000d66b1d5433f1aa5305cd1edce7c22de466", "0x00000000000000000000000000000000002331546a256b8a3b751956806680d4", "0x000000000000000000000000000000e97954ad6cd6f45fb15c91434121db4304", "0x00000000000000000000000000000000002e20a97e09d50f227ced47e7a98250", "0x0000000000000000000000000000001ebbc27eb9ebededefba79522eb58ae89b", "0x0000000000000000000000000000000000090efa4974e566e81d1177b85a30be", "0x0000000000000000000000000000005eafa070b9c9632404052642e3bc14f9fd", "0x00000000000000000000000000000000001489068864102daca6a6b8bc4d448b", "0x0000000000000000000000000000009ebc91aaaac036a6477cadbe54e8556dfd", "0x00000000000000000000000000000000000ef6d835e2ed3343b95c82c8c54037", "0x00000000000000000000000000000033b28b529dff46e93af4e7422530478e4a", "0x000000000000000000000000000000000020a86c2f8591bf190bcddcc03c42fb", "0x000000000000000000000000000000a9679d0acc088f7dc27bf6d866bcd2dda2", "0x00000000000000000000000000000000002fb9d0d2d4099402bed74f738f64cc", "0x00000000000000000000000000000023b09f876a29a061582848a8b9a5870c12", "0x00000000000000000000000000000000001d5bb906f03f0d49e9c4791bc43af9", "0x00000000000000000000000000000017aac9854ea240d8ec97bf760c4d4ba870", "0x00000000000000000000000000000000000b227a556c414ada0dc75bb303e30e", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000009b624fa65d1a24b7f14a8f25f3789622af", "0x000000000000000000000000000000000013d47bff8c630e847b70e2732fd3f0", "0x00000000000000000000000000000061d21663e93132f32921075f4c936a84df", "0x00000000000000000000000000000000001a74ca4e118fb480b9b999902989a3"] diff --git a/noir/noir-repo/tooling/debugger/src/context.rs b/noir/noir-repo/tooling/debugger/src/context.rs index 0d348cf172d..dde3fe84d88 100644 --- a/noir/noir-repo/tooling/debugger/src/context.rs +++ b/noir/noir-repo/tooling/debugger/src/context.rs @@ -976,10 +976,20 @@ mod tests { let brillig_bytecode = BrilligBytecode { bytecode: vec![ + BrilligOpcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(1u64), + }, + BrilligOpcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), - size: 1, - offset: 0, + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), }, BrilligOpcode::Const { destination: MemoryAddress::from(1), @@ -1036,7 +1046,7 @@ mod tests { }) ); - // Execute the first Brillig opcode (calldata copy) + // Const let result = context.step_into_opcode(); assert!(matches!(result, DebugCommandResult::Ok)); assert_eq!( @@ -1048,7 +1058,7 @@ mod tests { }) ); - // execute the second Brillig opcode (const) + // Const let result = context.step_into_opcode(); assert!(matches!(result, DebugCommandResult::Ok)); assert_eq!( @@ -1060,26 +1070,50 @@ mod tests { }) ); - // try to execute the third Brillig opcode (and resolve the foreign call) + // Calldatacopy let result = context.step_into_opcode(); assert!(matches!(result, DebugCommandResult::Ok)); assert_eq!( context.get_current_debug_location(), Some(DebugLocation { circuit_id: 0, - opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 }, brillig_function_id: Some(BrilligFunctionId(0)), }) ); - // retry the third Brillig opcode (foreign call should be finished) + // Const let result = context.step_into_opcode(); assert!(matches!(result, DebugCommandResult::Ok)); assert_eq!( context.get_current_debug_location(), Some(DebugLocation { circuit_id: 0, - opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 }, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 4 }, + brillig_function_id: Some(BrilligFunctionId(0)), + }) + ); + + // try to execute the Brillig opcode (and resolve the foreign call) + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_debug_location(), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 4 }, + brillig_function_id: Some(BrilligFunctionId(0)), + }) + ); + + // retry the Brillig opcode (foreign call should be finished) + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_debug_location(), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 5 }, brillig_function_id: Some(BrilligFunctionId(0)), }) ); @@ -1101,10 +1135,20 @@ mod tests { // This Brillig block is equivalent to: z = x + y let brillig_bytecode = BrilligBytecode { bytecode: vec![ + BrilligOpcode::Const { + destination: MemoryAddress(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(2u64), + }, + BrilligOpcode::Const { + destination: MemoryAddress(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress(0), - size: 2, - offset: 0, + size_address: MemoryAddress(0), + offset_address: MemoryAddress(1), }, BrilligOpcode::BinaryFieldOp { destination: MemoryAddress::from(0), diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs b/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs index a2eacea4b46..7e11e0d9d52 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs @@ -316,7 +316,7 @@ mod completion_tests { mod something_else {} use crate::s>|< } - + "#; assert_completion(src, vec![module_completion_item("something")]).await; } @@ -328,7 +328,7 @@ mod completion_tests { mod something_else {} use crate::something::s>|< } - + "#; assert_completion(src, vec![module_completion_item("something_else")]).await; } diff --git a/noir/verify_honk_proof/Prover.toml b/noir/verify_honk_proof/Prover.toml index 5bdebb476be..3f6bf0b427a 100644 --- a/noir/verify_honk_proof/Prover.toml +++ b/noir/verify_honk_proof/Prover.toml @@ -1,575 +1,4 @@ key_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" -proof = [ - "0x0000000000000000000000000000000000000000000000000000000000000040", - "0x0000000000000000000000000000000000000000000000000000000000000011", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", - "0x00000000000000000000000000000000000000000000000b75c020998797da78", - "0x0000000000000000000000000000000000000000000000005a107acb64952eca", - "0x000000000000000000000000000000000000000000000000000031e97a575e9d", - "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", - "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", - "0x00000000000000000000000000000000000000000000000d722669117f9758a4", - "0x000000000000000000000000000000000000000000000000000178cbf4206471", - "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", - "0x000000000000000000000000000000000000000000000007fd51009034b3357f", - "0x000000000000000000000000000000000000000000000009889939f81e9c7402", - "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", - "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", - "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", - "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", - "0x0000000000000000000000000000000000000000000000000001b52c2020d746", - "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", - "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", - "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", - "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", - "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", - "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", - "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", - "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", - "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", - "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", - "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", - "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", - "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", - "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", - "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", - "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", - "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", - "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", - "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", - "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", - "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", - "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", - "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", - "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", - "0x000000000000000000000000000000286fcda0e28617c86e195005b9f2efc555", - "0x00000000000000000000000000000000000dc409eb684b23f6a97175bcb9b486", - "0x000000000000000000000000000000e8de6a193cd36414f598bc7c48d67c3b59", - "0x00000000000000000000000000000000002a8a791544cad8c712de871e3de50a", - "0x000000000000000000000000000000d6f1e64b562df0f17ecc6aa46392f8d5a3", - "0x00000000000000000000000000000000000aac977763f33fd6a360ccc50a827a", - "0x000000000000000000000000000000899fa957f5597c6419e3ead9843d21d917", - "0x000000000000000000000000000000000016c4611846952bd6833c35fb11c0da", - "0x013dbfbfbfb2ae7d524edb15343e551d9510b3116223baaa67312d17652f2fb1", - "0x2f268eb3217ef1ac66016aa14d43033f932335371795b5e6dcb0c87c8ad0d050", - "0x2d5dbd52e00ae837e9868289fbe9057f16ea5b76c7e362603e8883f0de4b3e94", - "0x0e357b6a266c20d5e546c2931475eb044d7e75e08ec31b5e8623aec30f964323", - "0x0a9ace4dea44d0a2e8d12d495a683f508714356656aea3882436b729ead24165", - "0x0c17102a98ccb76faf0f78d669ee9cfb694849896787c985225d92e1af3cab35", - "0x09cc7cb719deb139c84fd9fa273e862a1b5d1cec2501c6cd8ba3c37ca06ac07f", - "0x15a0369f3f95d53687dfe79483baf75597d8b281fe0595caf1f7c9ccf99d985e", - "0x17fb53a42b3d1fa5d26ab19dfcc0d74d1781cee0be98dcc492c22e8f3442c4db", - "0x291d6810fc6afc5c2254fd283843a74c85a77275eee3049ea8ed9c88e02a99b8", - "0x0ad40d1627c31247dfb894584a71f8599cfcb85afe84b20186fc07fccae1aa4a", - "0x251cd908fb4e9fe88660f2303f8d7e4d7886da32fddc0319a842b99543659c0b", - "0x1885bdea3dd82085ca67502ebec8ad87213493e18a06cfa27e2c69810481b4a7", - "0x239ab5ba86866bc6705091f82a6a29444dc76b0e7d94cede7eb745cce36ab2cf", - "0x088d29a03baa491845d152124189dfb8bf70ba9bf1fb00c379199dbb0195c663", - "0x18c9fbe3227988d2da599eba82d60f4de25b442b663585fdc611e37305fa77fc", - "0x010242ae641a8cc4d06b5d24e38d9fa6254f981e28f238ccf6aad580f780d3f5", - "0x00128d34b122e84d7e23276b1f13f5789a562e82c727e9ffcfd7bbaccbe69e04", - "0x0776defaf478bfea4db2698542314e27213f63c96e41f98d4d82a47ed6fab55d", - "0x273014a360eaaa493e398df82f18d9cae37f4b6c0ead20100cad3f5491805298", - "0x2b13528eb9ab6fa705f2b48c9ec6ce054ac984e3adf17d4d73431e8456bf4a3c", - "0x22dafe1d63e39cd2effb236da2e131ee1c8cf4049ce504431dcaf98f75c47ad8", - "0x1afb5bc7eb8d30d807101357bb290f9c3113523f4aacc1154a27b075e46a4fa4", - "0x0782dd7df679163e5f0c126abc901d00f3d7d0856b4c02a199ab691ecd7566e6", - "0x2e556c722c99a84a09ffdcc719178277f8e6c9e31a4769270e3b522b944b8ea2", - "0x1be933a48dca8ef26202d3f135998ac8bed6947020b7447ffb6033b0e37f2065", - "0x2d8ebae210848de2464f5435f1fd4b5467ee938910d7779002614943060bbb32", - "0x2da854bbee38a94a6a9c2c85dd05bb4c879173720b67f93f78b9de93cdb427b0", - "0x0fa2649472af2e79489c466b58002f8f284f953085ac0a98dfabee85b78f63cf", - "0x304a09437636026ef0746c4b8ac1ca0ff250c5630fb5bd03ddafddd7cbde850e", - "0x0c83bb3c6ee0faa1646ee4d8dd83f67ec98e5d63ac802f7bdebfcdf21dee62f1", - "0x229d7e4524b30c18a6b94f0054e6d2ea8eb2396f58f9c808d2c9f991e2be2399", - "0x1265bf5e1aaddeae09242b1435e2f8f9e7487bf76a0461752777f6ea1ff75ad6", - "0x2f32f53281b7a363d6bec84ca21c71c3206d906b036e8b36b0702780e3b1b870", - "0x017fb18c9aef4d6d2bc99f5d7f9a002c8921fcd7c7ba69bf05930b55c2829cb7", - "0x2ec761c02ef6f2eefb7c9b2d6df71795d0ce0820f86797e2e11415cb5b122f22", - "0x2b1722960f42a1b40ffae3e4b9419fc8ff5cb8139a2c7e89af332ba2e95c1b5f", - "0x2dafa15594da2318245475c77eae3712429226b3005852e70f567efff0a7d79a", - "0x2ed44d7e3d5f44ac8f7c144ee0ba9d369c82428827c19b010384708bbc52a3f9", - "0x2777eedda697c7f90aee44fa97cfe62596d16c43fa3545b48d622023ca7a446a", - "0x1a47a5c1b0f41905aa0bad6248be8c7887ddea3ad9dfc8462b23a95b073c8a49", - "0x093656d571e84ac676a265dd509c98513039552b7a24e001b003ca618cc4ea5c", - "0x15c901e8a7ff0f1ae1989b5cfb687975c16716a8014a4052d527d4db4ecbaeb4", - "0x08bfa20e83096b0be58e4c96232510c8ef9824c0a62b91ffcc4592b217753a72", - "0x021913efbdfbc73aa5f4a97c79f352ac61f71248947f5eb5713c1b107c632703", - "0x00df89625aef270fab2a8c33ba742e1375423f4cfb3f63514ae748e004bb8cf4", - "0x2455f76c8ee59e93cbe7fe192cf0f766e1399617cabfa230cf27ca2a18cd58d5", - "0x150c3e56ea4f6442ed6b11030c98682a8f5e3c9cd6fd18949254a7c79b3cb5b6", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x01e89c6fe644aea7f63301278dbdb4ea29cf4d33f8b0cdcd79cb106e0bf0a753", - "0x2d49d23421e253903b8a5d0911642b9ce218cef4e350cf8689704eb1f3ae38d4", - "0x072956ca447343d788791fee1ef222f280048ad4aefb6cb7bc96b538f482f525", - "0x168176bf15c8ca63457acf05efbe54af452ea41f935ab82c2a96fedde10ba52f", - "0x20a13690f13491f7f3b756a1dc3b69a3f96d78355c70289583032a593bfc87bc", - "0x273e0a32ab3ef0d3f179b62520b31015ccfc8b53c76a1bb323b41e40ff954596", - "0x28019d4b05546b44e35d5dc74375b75dabb6fae49a07381605c60423c6163d26", - "0x10beda0b8dd484c63f0937820e2c7e9be832a0031efe3557631608895255ca5f", - "0x095a8f04a901526e4d70b1560bfff29b5a3c30347725d1e420c1b30ee2bf8a1c", - "0x1fb742e863a5c76262ffec93b3351405b0840b326fa5fffd73f40abcd5f05f05", - "0x11fa63cfcb2e603fe4e4668d75f05a2cf22650b84a91d1753e83f0e7ae83b4ad", - "0x2872e3d3c431a8b7ee4cec1c2a999a42c40ae33382fbba80a6d4c1a39b2d57a3", - "0x17e8c2a5f809f9935d7c6d7cb2f8859a513864b53f53de3d2a14c74cd690bd1a", - "0x20a552298d691393ae401382b3015689231ad988d3eb0521d414dcd2e8781053", - "0x183eb6bca59a141b4e8136179a258272ec9c25ec80bdb0458b6880c711707a28", - "0x03cd147a2a4c8dc272f3e240b8b0090d45e994e5fd40e07a54f6765795cd5ef8", - "0x082b135b3a20da4c766242b4258e27dbc050e4b8958bb15431626f2eeed9bd2b", - "0x28c894a6a719a32fe8d78ded46bc685ba035e5579c88fbc5bcbc0f09d8c5268b", - "0x06418cceff50837f923e63a37c2c534d13d9f59793c3aa6274813baa64d1899e", - "0x2b4a27b672f85c4fc697605da213de8b950a629602c5b8c6403e6c1c1065388a", - "0x0e2b817c6a79d6d1027f0376fb26ec81a140a4402e2dcdff6152cf01f2f4dbf9", - "0x2ae0fbce87dc53f0ff5473117e1c49a8197a14f8eaaec00cb5b10f94e844111f", - "0x2368004a1dee06f505e75ada3e9f8cc4c801f6a2068620da51ba11f537453835", - "0x2009df8e6f49f67dcaecb93e4a9ef81aaff096136d26f0fe691e14cd580c47da", - "0x2e512617136e8da2817856e57f13087a75fcc512faefc6d4b2eedd73c58a9b35", - "0x2848fcd535bd7c8017ca331a14919aa492ed05b04e9d0745480d291205eac8dc", - "0x19bb0990cb37f3a8f6c3db78219b07d6accd08e889586660e92dd6000755f09a", - "0x15520c8158b2e36c40c5fa46d5281c45d3df2c7f5d974a1f9549bfca6cbceaea", - "0x0e285f4df658d99922c286c5a253d6f6f37aa6c52d7a0fc1a20f3e6da9df23e1", - "0x0f9cd4667f4c1e86f83eda9e752a05c0cc630b0827a93a68322fa258dffb0f24", - "0x12d8b0dbbea3dccfe5d2dd090daf8ab4d2fac74fada9c49875b0c9122663a8ad", - "0x2e8c814d93f027ecff08c4e58555aadfc0f9ec3889eff2150f2b5bb6c557add0", - "0x013516a1456c5831aba87e4057878f6f3f18471e0674fd1e89be3e18351ec394", - "0x14418aa79dc84fd791d5638bdc103786ef8181a714ee8e022d3a1e792cbc7959", - "0x14418aa79dc84fd791d5638bdc103786ef8181a714ee8e022d3a1e792cbc7959", - "0x25c5e6c96a39bb36e19106d4049b675f0279084cc757c4e2acf6e497c61056a2", - "0x231aaafcf2a4c6fd8da18ce5ae5b33790f2c306a2692c6383c9a0787c50ac269", - "0x0a5f7665f0997081f9b38ec64e9a18542ac3a9648060f8cc720fc04669224730", - "0x0f1c9d9d1ac6f62825c6038117ed30540be434e8fd2d88150dcd4fece39b335a", - "0x1308871c8fcb09f07e5257f5cc5678d98842a8d18b2af09b5132d9af3cb1893e", - "0x28801985290dac4eba72ed01ee06fe88f6fc533dc1a46bd86e2d35be8021b042", - "0x14407f38cfba3cc61fca173b41133ab05a1c176caf8bb597588b01817e9eeaa3", - "0x0ea1a9f6f95f6193e512a7bd3db0c147f66687662934aed53cb657935b1e4eb9", - "0x1bc4ab6eacd61b5fd9e414b0186ef5deaadaf59aa9e53cb8d8812255baa28109", - "0x00000000000000000000000000000093a4da68a2fac0ee94841efdfc57eb748c", - "0x00000000000000000000000000000000001c22f1f5f927bee6adb649cc132391", - "0x0000000000000000000000000000003d0c2acea76c551f58876b3c35f19f345a", - "0x00000000000000000000000000000000002e94fded0a0b7f4fd1c882fd2a4e52", - "0x00000000000000000000000000000022e23b6fa0f72844bf8f60ea140cca5663", - "0x000000000000000000000000000000000013380f284bf3cb98b9a7cbae7d702b", - "0x000000000000000000000000000000942a13cf93056815c3f7439c9eed0a103e", - "0x00000000000000000000000000000000002be14bec02c6dae4625d32866de4fc", - "0x000000000000000000000000000000e2a2c75dc664c12695b4f7795c61f92669", - "0x000000000000000000000000000000000000725da448f376bde6cf63bcf79463", - "0x000000000000000000000000000000f54eee585f8ab367dc66a587e1d4cdbd8c", - "0x0000000000000000000000000000000000071106624ae5623a070f0addc18433", - "0x000000000000000000000000000000d60352bea3b2adb311b1a3beb25acb8aed", - "0x00000000000000000000000000000000001965b7c781e33f94e90c743c7881ed", - "0x0000000000000000000000000000006458a2aa57539e2b192f9c3ed69f9fb674", - "0x00000000000000000000000000000000001fc9c667723a4e66d752c6b426d444", - "0x0000000000000000000000000000008d1ff1c5d59a463c5b46bcf52f41ad3c63", - "0x00000000000000000000000000000000001b3e73df070a35c49a03fab1c76e9b", - "0x0000000000000000000000000000001c17a62b6c0a7ab14de83391e06f780adb", - "0x000000000000000000000000000000000012c7fbe2591b9ae72dd526e4ed1d7f", - "0x000000000000000000000000000000a758fa0c72d6a93155cb18b3fcc7defd34", - "0x00000000000000000000000000000000000cea12961770ce7cb6f2a4aed009fe", - "0x000000000000000000000000000000ef6e9647803aac315fa6d287e0e66f4767", - "0x0000000000000000000000000000000000259a82b8d6c6015cc51d2681f26ad4", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000008152b373c87004bef7d2c55ec8c540b67f", - "0x00000000000000000000000000000000000a55be5fdcb0a0dce4976d7bb78b0c", - "0x000000000000000000000000000000f749ea03f04ac964706139b9d1db595ecb", - "0x000000000000000000000000000000000013218e14dae80c066b4e46e9309fb2", - "0x0000000000000000000000000000004bbd7f950c36ce69db39e2b234a9e3f9b0", - "0x00000000000000000000000000000000002a0c3994d892ca5ea26984abbb30fb", - "0x0000000000000000000000000000006c1b39306846620bd546ac2c897834f259", - "0x000000000000000000000000000000000020350b9f507d6e25961a11be3e494b", -] -public_inputs = [ - "0x0000000000000000000000000000000000000000000000000000000000000003", -] -verification_key = [ - "0x0000000000000000000000000000000000000000000000000000000000000040", - "0x0000000000000000000000000000000000000000000000000000000000000011", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000003", - "0x0000000000000000000000000000000000000000000000000000000000000004", - "0x0000000000000000000000000000000000000000000000000000000000000005", - "0x0000000000000000000000000000000000000000000000000000000000000006", - "0x0000000000000000000000000000000000000000000000000000000000000007", - "0x0000000000000000000000000000000000000000000000000000000000000008", - "0x0000000000000000000000000000000000000000000000000000000000000009", - "0x000000000000000000000000000000000000000000000000000000000000000a", - "0x000000000000000000000000000000000000000000000000000000000000000b", - "0x000000000000000000000000000000000000000000000000000000000000000c", - "0x000000000000000000000000000000000000000000000000000000000000000d", - "0x000000000000000000000000000000000000000000000000000000000000000e", - "0x000000000000000000000000000000000000000000000000000000000000000f", - "0x0000000000000000000000000000000000000000000000000000000000000010", - "0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84", - "0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae", - "0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16", - "0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1", - "0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c", - "0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7", - "0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8", - "0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c", - "0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5", - "0x00000000000000000000000000000000002002681bb417184b2df070a16a3858", - "0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511", - "0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223", - "0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7", - "0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c", - "0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130", - "0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f", - "0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3", - "0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592", - "0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3", - "0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1", - "0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0", - "0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c", - "0x0000000000000000000000000000009f825dde88092070747180d581c342444a", - "0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01", - "0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff", - "0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9", - "0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1", - "0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b", - "0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2", - "0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f", - "0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0", - "0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349", - "0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8", - "0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2", - "0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556", - "0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d", - "0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb", - "0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d", - "0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8", - "0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862", - "0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e", - "0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830", - "0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f", - "0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe", - "0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb", - "0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56", - "0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc", - "0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4", - "0x00000000000000000000000000000029a17181c7934fc3fdbd352eac5cb521b9", - "0x00000000000000000000000000000000001f497cbf5284ff29a2d336e5991999", - "0x000000000000000000000000000000072bd9c0c6beda1fdee6d4ff0432ba9e1b", - "0x000000000000000000000000000000000013ea38a0bd2aa751a490a724fac818", - "0x000000000000000000000000000000c599f63dcd3edd49f08ae5c3141c1e3493", - "0x00000000000000000000000000000000002bdb36be0bea09950dd32a8ccf6fbc", - "0x00000000000000000000000000000047f27f29724e7f19eba0340256a0bd4b7d", - "0x00000000000000000000000000000000001c1c5ccf87a962129ca785f8f35120", - "0x000000000000000000000000000000c5c71efdae00679bbe4a95096e012b1817", - "0x000000000000000000000000000000000017a365de041e317817d0135f2b48e0", - "0x0000000000000000000000000000008ae711ac402f7848d719c93a89ba8d39f1", - "0x00000000000000000000000000000000002b6fb40ed8a1935226f4f9786a0499", - "0x0000000000000000000000000000002f03a71501d83de1da5715a4e9462d6198", - "0x00000000000000000000000000000000001644064443b8546f48eae693af47b8", - "0x00000000000000000000000000000083763ab1b6e8fe269b2fe4c7b9c448c08d", - "0x000000000000000000000000000000000021d7cc18c59676a8eeb47c0111c251", - "0x000000000000000000000000000000b5f937153073e03ea7d51a996e0ebc2e6b", - "0x000000000000000000000000000000000011ddd0e26457373eb06e0493177672", - "0x000000000000000000000000000000c5f6eb9f6fc8fa99811a4a88c74a6d018b", - "0x000000000000000000000000000000000025bcd07a0732c123567834f5109558", - "0x000000000000000000000000000000aeb08a0b1a4442189448b4e97490568146", - "0x000000000000000000000000000000000002a1744e4771705536a88f07e0f90f", - "0x000000000000000000000000000000b938568293bd0724b0ea76c2ec34c4a829", - "0x0000000000000000000000000000000000053296e8f3b9ad3af877dfa9c7c2a7", - "0x000000000000000000000000000000f0ca1db6323996eba26bdc86dafef9d10b", - "0x00000000000000000000000000000000001441a46c58af03d5645d52721d956a", - "0x0000000000000000000000000000008bbf8f884013c66c28ba09c2fbd573b656", - "0x0000000000000000000000000000000000206c391ca06fac27d1908e94570243", - "0x0000000000000000000000000000002d4f5aaed88ba4f79612d53b804ca8f194", - "0x00000000000000000000000000000000001674011c96392df08970fa6b7b4cb8", - "0x0000000000000000000000000000009f88297c1729d76c4d9306853598c91325", - "0x0000000000000000000000000000000000256f51adfcacc3c1e340be4d32d3e9", - "0x0000000000000000000000000000000ab9955eec0d74eb799afed2a802b24d75", - "0x00000000000000000000000000000000001fcbe43ea105b30d36ed0b21b03411", - "0x000000000000000000000000000000d66b1d5433f1aa5305cd1edce7c22de466", - "0x00000000000000000000000000000000002331546a256b8a3b751956806680d4", - "0x000000000000000000000000000000e97954ad6cd6f45fb15c91434121db4304", - "0x00000000000000000000000000000000002e20a97e09d50f227ced47e7a98250", - "0x0000000000000000000000000000001ebbc27eb9ebededefba79522eb58ae89b", - "0x0000000000000000000000000000000000090efa4974e566e81d1177b85a30be", - "0x0000000000000000000000000000005eafa070b9c9632404052642e3bc14f9fd", - "0x00000000000000000000000000000000001489068864102daca6a6b8bc4d448b", - "0x0000000000000000000000000000009ebc91aaaac036a6477cadbe54e8556dfd", - "0x00000000000000000000000000000000000ef6d835e2ed3343b95c82c8c54037", - "0x00000000000000000000000000000033b28b529dff46e93af4e7422530478e4a", - "0x000000000000000000000000000000000020a86c2f8591bf190bcddcc03c42fb", - "0x000000000000000000000000000000a9679d0acc088f7dc27bf6d866bcd2dda2", - "0x00000000000000000000000000000000002fb9d0d2d4099402bed74f738f64cc", - "0x00000000000000000000000000000023b09f876a29a061582848a8b9a5870c12", - "0x00000000000000000000000000000000001d5bb906f03f0d49e9c4791bc43af9", - "0x00000000000000000000000000000017aac9854ea240d8ec97bf760c4d4ba870", - "0x00000000000000000000000000000000000b227a556c414ada0dc75bb303e30e", - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000009b624fa65d1a24b7f14a8f25f3789622af", - "0x000000000000000000000000000000000013d47bff8c630e847b70e2732fd3f0", - "0x00000000000000000000000000000061d21663e93132f32921075f4c936a84df", - "0x00000000000000000000000000000000001a74ca4e118fb480b9b999902989a3", -] +proof = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", "0x00000000000000000000000000000052eebbd1f6f7554e837f60c44000ed14b6", "0x00000000000000000000000000000000001c1c045a3ec94b8801f2272cc0b3f4", "0x0000000000000000000000000000004d2ef74134578f6b431a9df071ffca4292", "0x0000000000000000000000000000000000291326ade7aa6f0dfc8900eab5580b", "0x0000000000000000000000000000002433eec6418a6dba820c9527e2581fc8bc", "0x00000000000000000000000000000000000e88b7daad19af2ac2f9bdf9e50ee2", "0x000000000000000000000000000000dcfce2c427155cc3e4d035735d3dd5ece8", "0x00000000000000000000000000000000002d7d473cac1a15d0fee8b22c1a7b3e", "0x23fb9503f571d567261006e2ca8b4326d325820140b488bb71617583602f4e3e", "0x0c68b96eebbfcac292403ed3b6f61536550e66473904e7d5d28080108fd0b1c3", "0x08d3bdbefd6d437c50fb9e3e3861913433e76577a18d81aa0ea4b8843e55f9ae", "0x08f6173fe87b72da6d821a496eb99b0cfe0ccadcffd25e5a3b718d83ff9adb1a", "0x1e6bd0a24c2cc58c93cf255cc68dd0c57299c99fd934267906b34facb0145cf4", "0x1175996557630bc376d38636f72b277cb8d54a969a39988a7e78f464c03eaeda", "0x03c3bd1f43baf44de0d9bf0f474c5df04b182214d57a196a717aef8868f9948c", "0x27306ffc7a96c8c27c9812d9dfa649ab6897b69125939aabe814e07d105daa32", "0x0c7f0b70aa08158e55bb39471609782656793ac76a03f2b64dcd135e6542592c", "0x03885b9eff8dac38a64779e3aba31f18c74166892cef9c5081ab57f6daf59865", "0x18dd8385333838c514fd11f36469c88e7ea5f6440aee17fa93c0f03c765d4ced", "0x08ad5bc6c05ecc9ae0d8f0b3196f229a53dbe753f41c12c52045c40e7d8220cc", "0x2f308380f90378084075f2bafa73228b17cbdfc2d693f9aaa1e5089557d0f32e", "0x2d3407e6de05e5935a31037c3db88069d0c41ec86cc8dda815048d6ce76f7a5f", "0x108c231f660e75f209201507a2dba6fccf99734ad91db8ecea675275afdf3ce1", "0x0e68df40e8c467a617229ab0f1dc0d4a04254492e709333d623c0963518dd6b4", "0x290650614292eec7c4f26fd402a047298f1a618dc8ff7de615752f737df7d515", "0x0de290891aaf146fd890a3cd5c25025113df2ec4d0a134513a2f397eaf4e3ea9", "0x25521f6f658bd20d9aaa8041164509b7b8d96fc5ef385f6eb6582375d1a86168", "0x0e9ab2f2f06220644c41fb09456d91751c522b015622f30568e66457f647a2bc", "0x28364f88f1e9c7d8e7767a3b954c5daa29223d646279930b34da51351dc01992", "0x0560c214728aacc262eeee0037be142d81aec26a1f5a9cf0606c4236ed344aa8", "0x1faea1662601fa01ad93d160277a1c81f2c60a761b74660f24a596ec8cb783e7", "0x0e703bb7bbf3a8bb8211715d86a1becb7aa3271f51d6001d5d3042faa7465df9", "0x0cc5b499ea9d9cbae4a0e33a5b601a7f7b686d6980dc0dd5bae4382a8ab1c7c7", "0x27fae143a80a37af95a47d5953096eef9b1127b5475480b8a6ecebdb00a65e23", "0x02cdf7c51d9182fbe07e7768ed0fcfe452ef70fc2ac87dc38fc0d4137bdf4aec", "0x14838df5a54d57d0a28b0375107bb7e7e7259c576a08ea39db6af8b0341d2911", "0x1b1fb0b1242e17beebb218c4ec88c830accea9bc93deec6d087d36d4d8de31fd", "0x1a8c0bdf35e674aa37118f5ad7fe6b62c65d8502e9697b3a92dfda8a1923d110", "0x2819aaa537cf012ceb48a8c8036b6fee492eeeef6698dcf8e3bc825d71efa3f8", "0x1ceedf534535a0d2a427b2ceeb3c8878a658b80eaf5210dbc0d32888fe3d05a7", "0x25c96dba803387eb5f3562785bc3bccddb7c9eb019bd4b07dd4563f77965c00c", "0x0353f3ff0f4f3da362b11eac12167dcbc9b3c76fb555f7e5534c14bb4c3f8037", "0x2904e33424ad29d38bda66a50b54a67acdf09be06a068ddc09d5eabdf9c2a9e5", "0x0b28534bf4b58e7f46c4a7514f3b521dd47bbac2a3adf09387baf19ec8df39c5", "0x1628b67c5d7b8c4cb5d8cdd2d0fd1d92bea3bfcf490fba7f16447cb686d7a388", "0x151bde642447aaf993e737329a3b81c6e243eecbe6a7bb43cdb8ffe74b2c0484", "0x07b319f585e9a9a3883deaddd9b0f43c844cbc7477636034f1543ce9f98821bf", "0x2c8738d76925012cc029f5b888be3cae165daa6beb22b5d73f017c918d891c34", "0x118fff7a26b04a6476c21267a3a4e96247640f6eabd05a05f1a94f881c6ee32b", "0x081d82e0808b6d444b03e1d722375adef2659d5914faa3d9ca4cb12c912be257", "0x18426c5ff5a3140f19bdc05e247cc05e1f70e1ea482b2a2b21f4930a494d7a61", "0x296babb7c6a72783d92bc3dee7f90a97302d64a518faeec0f42af4f599ccc0d1", "0x03337dd83835a2e9fe02c97056360eec725d55b01f039663108939f0333dba11", "0x11a796e7e6f1081be5aad42b475dc224f9547769bc6b358af63207fe0d324a4a", "0x2419618a28070cb7af904460207371f5ff9fa0939f6a0148add60ede530b0f14", "0x004d323457b070f3f41a4ce1ad5a867b3dea1a592bccb40c4d69c8521d9682b6", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x2d6ba30a2a23364900cf52019e2d19574813fe4922763a4e281c58c400ffce14", "0x06a0c085375f88283bedf3a1fc76ef35490655f372e2a985842a9375383b69d7", "0x219b78e5cf2ab2e35edfc8e40362062081a24ff4e9c9d15afa254c2a02d6d4e2", "0x182f29b047e6167c338c36d31685a825c66f327336545c623e7a6bd18e4fa97f", "0x1686460e2586e702724b9daf02315a33ddf5cbd275cfadbc3858f9ef3fe97133", "0x2183aaf585ac708b4000a5b88cf5a767356677087133bd90fff1c3e030b91f1e", "0x27dfa9c69d03c7776fecac8e0f56162caa95f44692cdae91f5b52dfc97eb9006", "0x10a9959de8c6d238c6c6dd68274cc9fc5b6d66759938638072d71659a2fe210d", "0x0e179d6215630fdd7d50362ade21893456d4b9a693e96152d9a6bac6518d4605", "0x0175b579d4e3b24eb0a319a6c79756c8a68ce2c1e0d0d8d1593d685125fbfb66", "0x1132bd3d531944f5024f2705d39b13e00ae90c246f6550c745234fd3d080712b", "0x1f2326f3955b431f2a17e937128b890aa366b107b69c61b8b45832fd06ce9e4e", "0x13576e6c03c3f2042c56113991821ec1f9dec46b6b0ff2748e037c94e6656c40", "0x00bb713034ce9d247110149e2a1754dc76f3ad700d420508148060091037477a", "0x25fb93286a48dc64c67ffac9e3f4a96b6c70bb87744e10e44a782117f8f537a0", "0x191227cd5e49d8a6b5aca93888b3286b41069df547e4bd91ffe65e48ab45b2a8", "0x120d4ac764ca4db67357140c8a8dd1523c013f747250a03a6130416669b087e1", "0x131cc1285b242d73eee36b79ccb3024525ae3caf0f91981cb89ec8d81b16a198", "0x0cacfa5aa1bc4624d5d476aced4d4c8026fb881679172dbc482d18772bc28c9f", "0x0e138279e8a4fe06018e9b9e649921500766e7a7afcc971f41732aa51ec31a43", "0x000000000000000000000000000000332f935a88cd2cc8a138d5ff2efe4cdec8", "0x0e1c2af7515e65c7ebced1a37faf4dbeef5c414f5601219d00d3844658b05a61", "0x12aff8e8eed2d2946c91652d448240590690672893b4759cdd31e1ec9ea45138", "0x1e89f396af25e81f9c4b3af2b0a15fd961789f3a8aa60edbdc4e8f2dfb610375", "0x29c05199f808bf38009ee7fa3c82b6aa5e3d65f180f49d4564c4bf6918399461", "0x019ce7ac46f4e5f1d4ce2d3866321506cea78ff5e5fe400d83b0395341cfe5d5", "0x20b40d1a69e62e7eecbf490915e2791975d3bca30859f237c56c4486e1fbb441", "0x243f7e62233a1f80ee17978814d7ab095bcc416d6bcee4583ce1167c7206b7b4", "0x0b6067a921e8d87bc8fd1af67382fbe2a27bcc833effa13fd7d85b5458d71e28", "0x30307a6766be04f3c50378d1b83f2e147e2ceef344d0c60e1abf939d29c26e27", "0x004c0ec19588b920084d00c6bfe0af4dbf83ca101eac5d833cb8191fe1c298b4", "0x00da79a40286bd8d3993b331a72f8195c7ba04bd863d1afd469bb094e29cc7d9", "0x115b70a2c50ee9abc28472ba8e820cfba158113a5a39c8e31817c84182d0503a", "0x09341d5c4b6d85bde38834a418a8ca375592c320c669bdd540c7ccee760f2ea1", "0x09341d5c4b6d85bde38834a418a8ca375592c320c669bdd540c7ccee760f2ea1", "0x0e63e927a9562ce0914fcd8892dff9a94ac722365ce21b8f5c75cc560b364e57", "0x05cf84989894e741a3e1cd815a8f84febfb08e61ee7b424c902fb02ca7d12e95", "0x1f958ad88d5e4a270f35e534154e7a519c5bbfab36d5084202d5b78baf63e09e", "0x21f0a33450db8821c2f8d042aae7e70bf05c9814b063e73c5e95f8ddba515a81", "0x2767a30fa0351c7deb2c8f542ecace4c41c1d136dd460dfad50b372f2a5f4b71", "0x137ee4ebfbc7227bf57ffc35d3368dd4f96c62911db9380aafa220d061c3b59d", "0x111515d3566611192f64e1e0848635ca6d7f73d8039d8b3522da1e2359e6d1b2", "0x2f6284e905c491b8defe4c467b2e664e2fbf144b5ca45e05c4a9d1aa8d41e149", "0x1e688ca09721459cd96d6af042716567a8f5fdb479f08ff9eff248c6013315a4", "0x00000000000000000000000000000015207c89ecabf752a46c0d5b8dbd296d86", "0x0000000000000000000000000000000000286c2b4d49249737816da8fd9f2753", "0x0000000000000000000000000000002492e649af820ca5d83e59823126c03bfb", "0x00000000000000000000000000000000001cdf1b636e33bf02a813687147476e", "0x000000000000000000000000000000b49023689f96212b8166d0c9b105e6df9a", "0x00000000000000000000000000000000000d9d27730e57d86079464ecd8d9edd", "0x0000000000000000000000000000005292b5583bd716a723bae47d344d655528", "0x000000000000000000000000000000000026651dba1a1074382c734163ab3614", "0x0000000000000000000000000000008984f01bc1f237c72fd6d2bb10cc21eb85", "0x00000000000000000000000000000000001029818de60ae9bb21ac2b5d5a4c97", "0x0000000000000000000000000000003aca28da52679f34e33756dfe00f1d8072", "0x0000000000000000000000000000000000124ecac53af720c02d18f54fd29100", "0x000000000000000000000000000000d09ed1c104d0397f046d89b8476f47e641", "0x00000000000000000000000000000000002c5094b27ad41c8a203b16dc74ee54", "0x000000000000000000000000000000bf8609068d29793771eb3f64e7dc3db96d", "0x0000000000000000000000000000000000225e220e16aedaecf2c10de6e41042", "0x0000000000000000000000000000006ae4f0d8baca7866ad4632141f90770cd7", "0x0000000000000000000000000000000000256cb979ab5bbe98be3a413ae8f246", "0x000000000000000000000000000000891f30bd3ac8e7e63e00db4951d518822f", "0x000000000000000000000000000000000014dffca5d842acfcd23fa491a7dae2", "0x000000000000000000000000000000af99905ea5b7a25f2172f044a59b90e67d", "0x00000000000000000000000000000000001e35bb78e382a5b98ad04b846df528", "0x0000000000000000000000000000003cfb75469b791ea188b8dfdff0f269e7b5", "0x00000000000000000000000000000000000e4fb9eb44a3d44d808794066f8811", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000c42f38f2993af03e18e76996c49f945c6a", "0x00000000000000000000000000000000002aefe820f0e4700abedd9fb6f046c1", "0x0000000000000000000000000000007a878e53414bf22854877c5066eaf916b8", "0x00000000000000000000000000000000001410a75247434da28c1ba6b64703bb", "0x000000000000000000000000000000bca902c1e2af8b47771e7eb42c3870f46b", "0x0000000000000000000000000000000000276eb602c3c232b51668d229d602b8", "0x000000000000000000000000000000dac1254c0753ee39d49d795bc6b3550ba7", "0x000000000000000000000000000000000007d60be9174146bd83f202aa062b92"] +public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x0000000000000000000000000000000000000000000000000000000000000005", "0x0000000000000000000000000000000000000000000000000000000000000006", "0x0000000000000000000000000000000000000000000000000000000000000007", "0x0000000000000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000009", "0x000000000000000000000000000000000000000000000000000000000000000a", "0x000000000000000000000000000000000000000000000000000000000000000b", "0x000000000000000000000000000000000000000000000000000000000000000c", "0x000000000000000000000000000000000000000000000000000000000000000d", "0x000000000000000000000000000000000000000000000000000000000000000e", "0x000000000000000000000000000000000000000000000000000000000000000f", "0x0000000000000000000000000000000000000000000000000000000000000010", "0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84", "0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae", "0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16", "0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1", "0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c", "0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7", "0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8", "0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c", "0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5", "0x00000000000000000000000000000000002002681bb417184b2df070a16a3858", "0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511", "0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223", "0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7", "0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c", "0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130", "0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f", "0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3", "0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592", "0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3", "0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1", "0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0", "0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c", "0x0000000000000000000000000000009f825dde88092070747180d581c342444a", "0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01", "0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff", "0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9", "0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1", "0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b", "0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2", "0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f", "0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0", "0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349", "0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8", "0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2", "0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556", "0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d", "0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb", "0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d", "0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8", "0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862", "0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e", "0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830", "0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f", "0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe", "0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb", "0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56", "0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc", "0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4", "0x00000000000000000000000000000029a17181c7934fc3fdbd352eac5cb521b9", "0x00000000000000000000000000000000001f497cbf5284ff29a2d336e5991999", "0x000000000000000000000000000000072bd9c0c6beda1fdee6d4ff0432ba9e1b", "0x000000000000000000000000000000000013ea38a0bd2aa751a490a724fac818", "0x000000000000000000000000000000c599f63dcd3edd49f08ae5c3141c1e3493", "0x00000000000000000000000000000000002bdb36be0bea09950dd32a8ccf6fbc", "0x00000000000000000000000000000047f27f29724e7f19eba0340256a0bd4b7d", "0x00000000000000000000000000000000001c1c5ccf87a962129ca785f8f35120", "0x000000000000000000000000000000c5c71efdae00679bbe4a95096e012b1817", "0x000000000000000000000000000000000017a365de041e317817d0135f2b48e0", "0x0000000000000000000000000000008ae711ac402f7848d719c93a89ba8d39f1", "0x00000000000000000000000000000000002b6fb40ed8a1935226f4f9786a0499", "0x0000000000000000000000000000002f03a71501d83de1da5715a4e9462d6198", "0x00000000000000000000000000000000001644064443b8546f48eae693af47b8", "0x00000000000000000000000000000083763ab1b6e8fe269b2fe4c7b9c448c08d", "0x000000000000000000000000000000000021d7cc18c59676a8eeb47c0111c251", "0x000000000000000000000000000000b5f937153073e03ea7d51a996e0ebc2e6b", "0x000000000000000000000000000000000011ddd0e26457373eb06e0493177672", "0x000000000000000000000000000000c5f6eb9f6fc8fa99811a4a88c74a6d018b", "0x000000000000000000000000000000000025bcd07a0732c123567834f5109558", "0x000000000000000000000000000000aeb08a0b1a4442189448b4e97490568146", "0x000000000000000000000000000000000002a1744e4771705536a88f07e0f90f", "0x000000000000000000000000000000b938568293bd0724b0ea76c2ec34c4a829", "0x0000000000000000000000000000000000053296e8f3b9ad3af877dfa9c7c2a7", "0x000000000000000000000000000000f0ca1db6323996eba26bdc86dafef9d10b", "0x00000000000000000000000000000000001441a46c58af03d5645d52721d956a", "0x0000000000000000000000000000008bbf8f884013c66c28ba09c2fbd573b656", "0x0000000000000000000000000000000000206c391ca06fac27d1908e94570243", "0x0000000000000000000000000000002d4f5aaed88ba4f79612d53b804ca8f194", "0x00000000000000000000000000000000001674011c96392df08970fa6b7b4cb8", "0x0000000000000000000000000000009f88297c1729d76c4d9306853598c91325", "0x0000000000000000000000000000000000256f51adfcacc3c1e340be4d32d3e9", "0x0000000000000000000000000000000ab9955eec0d74eb799afed2a802b24d75", "0x00000000000000000000000000000000001fcbe43ea105b30d36ed0b21b03411", "0x000000000000000000000000000000d66b1d5433f1aa5305cd1edce7c22de466", "0x00000000000000000000000000000000002331546a256b8a3b751956806680d4", "0x000000000000000000000000000000e97954ad6cd6f45fb15c91434121db4304", "0x00000000000000000000000000000000002e20a97e09d50f227ced47e7a98250", "0x0000000000000000000000000000001ebbc27eb9ebededefba79522eb58ae89b", "0x0000000000000000000000000000000000090efa4974e566e81d1177b85a30be", "0x0000000000000000000000000000005eafa070b9c9632404052642e3bc14f9fd", "0x00000000000000000000000000000000001489068864102daca6a6b8bc4d448b", "0x0000000000000000000000000000009ebc91aaaac036a6477cadbe54e8556dfd", "0x00000000000000000000000000000000000ef6d835e2ed3343b95c82c8c54037", "0x00000000000000000000000000000033b28b529dff46e93af4e7422530478e4a", "0x000000000000000000000000000000000020a86c2f8591bf190bcddcc03c42fb", "0x000000000000000000000000000000a9679d0acc088f7dc27bf6d866bcd2dda2", "0x00000000000000000000000000000000002fb9d0d2d4099402bed74f738f64cc", "0x00000000000000000000000000000023b09f876a29a061582848a8b9a5870c12", "0x00000000000000000000000000000000001d5bb906f03f0d49e9c4791bc43af9", "0x00000000000000000000000000000017aac9854ea240d8ec97bf760c4d4ba870", "0x00000000000000000000000000000000000b227a556c414ada0dc75bb303e30e", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000009b624fa65d1a24b7f14a8f25f3789622af", "0x000000000000000000000000000000000013d47bff8c630e847b70e2732fd3f0", "0x00000000000000000000000000000061d21663e93132f32921075f4c936a84df", "0x00000000000000000000000000000000001a74ca4e118fb480b9b999902989a3"] diff --git a/yarn-project/Earthfile b/yarn-project/Earthfile index 0098093957e..07be9672103 100644 --- a/yarn-project/Earthfile +++ b/yarn-project/Earthfile @@ -116,7 +116,7 @@ protocol-verification-keys: rollup-verifier-contract: FROM +bb-cli COPY --dir +protocol-verification-keys/usr/src/bb /usr/src - RUN --entrypoint write-contract -c RootRollupArtifact -n UltraHonkVerifier.sol + RUN --entrypoint write-contract -c BlockRootRollupArtifact -n UltraHonkVerifier.sol SAVE ARTIFACT /usr/src/bb /usr/src/bb txe: diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 66b44986cd8..dec28dc5228 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -92,6 +92,7 @@ export class Archiver implements ArchiveSource { private readonly store: ArchiverDataStore, private readonly pollingIntervalMs = 10_000, private readonly instrumentation: ArchiverInstrumentation, + private readonly l1StartBlock: bigint = 0n, private readonly log: DebugLogger = createDebugLogger('aztec:archiver'), ) {} @@ -124,6 +125,7 @@ export class Archiver implements ArchiveSource { archiverStore, config.archiverPollingIntervalMS, new ArchiverInstrumentation(telemetry), + BigInt(config.archiverL1StartBlock), ); await archiver.start(blockUntilSynced); return archiver; @@ -175,8 +177,12 @@ export class Archiver implements ArchiveSource { * * This code does not handle reorgs. */ - const { blockBodiesSynchedTo, blocksSynchedTo, messagesSynchedTo, provenLogsSynchedTo } = - await this.store.getSynchPoint(); + const { + blockBodiesSynchedTo = this.l1StartBlock, + blocksSynchedTo = this.l1StartBlock, + messagesSynchedTo = this.l1StartBlock, + provenLogsSynchedTo = this.l1StartBlock, + } = await this.store.getSynchPoint(); const currentL1BlockNumber = await this.publicClient.getBlockNumber(); if ( diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 1d7c6c81afe..2d1f5e52425 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -32,13 +32,13 @@ import { type L1Published } from './structs/published.js'; */ export type ArchiverL1SynchPoint = { /** Number of the last L1 block that added a new L2 block metadata. */ - blocksSynchedTo: bigint; + blocksSynchedTo?: bigint; /** Number of the last L1 block that added a new L2 block body. */ - blockBodiesSynchedTo: bigint; + blockBodiesSynchedTo?: bigint; /** Number of the last L1 block that added L1 -> L2 messages from the Inbox. */ - messagesSynchedTo: bigint; + messagesSynchedTo?: bigint; /** Number of the last L1 block that added a new proven block. */ - provenLogsSynchedTo: bigint; + provenLogsSynchedTo?: bigint; }; /** diff --git a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts index 3c6127e5b16..48b118a67b8 100644 --- a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts +++ b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts @@ -97,12 +97,12 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }); describe('getSynchPoint', () => { - it('returns 0n if no blocks have been added', async () => { + it('returns undefined if no blocks have been added', async () => { await expect(store.getSynchPoint()).resolves.toEqual({ - blocksSynchedTo: 0n, - messagesSynchedTo: 0n, - blockBodiesSynchedTo: 0n, - provenLogsSynchedTo: 0n, + blocksSynchedTo: undefined, + messagesSynchedTo: undefined, + blockBodiesSynchedTo: undefined, + provenLogsSynchedTo: undefined, } satisfies ArchiverL1SynchPoint); }); @@ -110,19 +110,19 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch await store.addBlocks(blocks); await expect(store.getSynchPoint()).resolves.toEqual({ blocksSynchedTo: 19n, - messagesSynchedTo: 0n, - blockBodiesSynchedTo: 0n, - provenLogsSynchedTo: 0n, + messagesSynchedTo: undefined, + blockBodiesSynchedTo: undefined, + provenLogsSynchedTo: undefined, } satisfies ArchiverL1SynchPoint); }); it('returns the L1 block number in which the most recent L2 block body was published', async () => { await store.addBlockBodies(blockBodies); await expect(store.getSynchPoint()).resolves.toEqual({ - blocksSynchedTo: 0n, - messagesSynchedTo: 0n, + blocksSynchedTo: undefined, + messagesSynchedTo: undefined, blockBodiesSynchedTo: blockBodies.lastProcessedL1BlockNumber, - provenLogsSynchedTo: 0n, + provenLogsSynchedTo: undefined, } satisfies ArchiverL1SynchPoint); }); @@ -132,19 +132,19 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch retrievedData: [new InboxLeaf(0n, 0n, Fr.ZERO)], }); await expect(store.getSynchPoint()).resolves.toEqual({ - blocksSynchedTo: 0n, + blocksSynchedTo: undefined, messagesSynchedTo: 1n, - blockBodiesSynchedTo: 0n, - provenLogsSynchedTo: 0n, + blockBodiesSynchedTo: undefined, + provenLogsSynchedTo: undefined, } satisfies ArchiverL1SynchPoint); }); it('returns the L1 block number that most recently logged a proven block', async () => { await store.setProvenL2BlockNumber({ lastProcessedL1BlockNumber: 3n, retrievedData: 5 }); await expect(store.getSynchPoint()).resolves.toEqual({ - blocksSynchedTo: 0n, - messagesSynchedTo: 0n, - blockBodiesSynchedTo: 0n, + blocksSynchedTo: undefined, + messagesSynchedTo: undefined, + blockBodiesSynchedTo: undefined, provenLogsSynchedTo: 3n, } satisfies ArchiverL1SynchPoint); }); diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts index f4ec61d3106..3b067f4e4ae 100644 --- a/yarn-project/archiver/src/archiver/config.ts +++ b/yarn-project/archiver/src/archiver/config.ts @@ -22,6 +22,11 @@ export type ArchiverConfig = { */ archiverPollingIntervalMS?: number; + /** + * The L1 block to start reading from + */ + archiverL1StartBlock: number; + /** * The polling interval viem uses in ms */ @@ -52,6 +57,11 @@ export const archiverConfigMappings: ConfigMappingsType = { description: 'The polling interval in ms for retrieving new L2 blocks and encrypted logs.', ...numberConfigHelper(1000), }, + archiverL1StartBlock: { + env: 'ARCHIVER_L1_START_BLOCK', + description: 'The L1 block the archiver should start reading logs from', + ...numberConfigHelper(0), + }, viemPollingIntervalMS: { env: 'ARCHIVER_VIEM_POLLING_INTERVAL_MS', description: 'The polling interval viem uses in ms', diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/block_body_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/block_body_store.ts index 9f1c5b3ac64..566e637e11b 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/block_body_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/block_body_store.ts @@ -68,7 +68,7 @@ export class BlockBodyStore { * Gets the last L1 block number in which a L2 block body was included * @returns The L1 block number */ - getSynchedL1BlockNumber(): bigint { - return this.#lastSynchedL1Block.get() ?? 0n; + getSynchedL1BlockNumber(): bigint | undefined { + return this.#lastSynchedL1Block.get(); } } diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts index 2fb206487b6..7ae29bd41b4 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts @@ -180,8 +180,8 @@ export class BlockStore { * Gets the most recent L1 block processed. * @returns The L1 block that published the latest L2 block */ - getSynchedL1BlockNumber(): bigint { - return this.#lastSynchedL1Block.get() ?? 0n; + getSynchedL1BlockNumber(): bigint | undefined { + return this.#lastSynchedL1Block.get(); } #computeBlockRange(start: number, limit: number): Required, 'start' | 'end'>> { diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts index 0d412b4b70e..38bfb1fc6ee 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts @@ -32,8 +32,8 @@ export class MessageStore { * Gets the last L1 block number that emitted new messages. * @returns The last L1 block number processed */ - getSynchedL1BlockNumber(): bigint { - return this.#lastL1BlockMessages.get() ?? 0n; + getSynchedL1BlockNumber(): bigint | undefined { + return this.#lastL1BlockMessages.get(); } /** diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/proven_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/proven_store.ts index 2009ce80627..d94b75b7ada 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/proven_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/proven_store.ts @@ -17,8 +17,8 @@ export class ProvenStore { /** * Gets the most recent L1 block processed. */ - getSynchedL1BlockNumber(): bigint { - return this.#lastSynchedL1Block.get() ?? 0n; + getSynchedL1BlockNumber(): bigint | undefined { + return this.#lastSynchedL1Block.get(); } getProvenL2BlockNumber(): number { diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts index 27e69b174e3..5094382b15c 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts @@ -83,10 +83,10 @@ export class MemoryArchiverStore implements ArchiverDataStore { private contractInstances: Map = new Map(); - private lastL1BlockNewBlocks: bigint = 0n; - private lastL1BlockNewBlockBodies: bigint = 0n; - private lastL1BlockNewMessages: bigint = 0n; - private lastL1BlockNewProvenLogs: bigint = 0n; + private lastL1BlockNewBlocks: bigint | undefined = undefined; + private lastL1BlockNewBlockBodies: bigint | undefined = undefined; + private lastL1BlockNewMessages: bigint | undefined = undefined; + private lastL1BlockNewProvenLogs: bigint | undefined = undefined; private lastProvenL2BlockNumber: number = 0; @@ -225,7 +225,10 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns True if the operation is successful. */ public addL1ToL2Messages(messages: DataRetrieval): Promise { - if (messages.lastProcessedL1BlockNumber <= this.lastL1BlockNewMessages) { + if ( + typeof this.lastL1BlockNewMessages === 'bigint' && + messages.lastProcessedL1BlockNumber <= this.lastL1BlockNewMessages + ) { return Promise.resolve(false); } diff --git a/yarn-project/aztec.js/package.json b/yarn-project/aztec.js/package.json index 81b120a2d26..40ff9add338 100644 --- a/yarn-project/aztec.js/package.json +++ b/yarn-project/aztec.js/package.json @@ -77,10 +77,12 @@ "@aztec/circuits.js": "workspace:^", "@aztec/ethereum": "workspace:^", "@aztec/foundation": "workspace:^", + "@aztec/l1-artifacts": "workspace:^", "@aztec/protocol-contracts": "workspace:^", "@aztec/types": "workspace:^", "axios": "^1.7.2", - "tslib": "^2.4.0" + "tslib": "^2.4.0", + "viem": "^2.7.15" }, "devDependencies": { "@jest/globals": "^29.5.0", diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index cf7198dd956..84e5a7d6c14 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -39,6 +39,7 @@ export { ContractDeployer } from './deployment/index.js'; export { AztecAddressLike, + AnvilTestWatcher, CheatCodes, EthAddressLike, EthCheatCodes, diff --git a/yarn-project/end-to-end/src/fixtures/watcher.ts b/yarn-project/aztec.js/src/utils/anvil_test_watcher.ts similarity index 66% rename from yarn-project/end-to-end/src/fixtures/watcher.ts rename to yarn-project/aztec.js/src/utils/anvil_test_watcher.ts index 2934be8b531..1b6e0cf7f63 100644 --- a/yarn-project/end-to-end/src/fixtures/watcher.ts +++ b/yarn-project/aztec.js/src/utils/anvil_test_watcher.ts @@ -6,7 +6,14 @@ import { RollupAbi } from '@aztec/l1-artifacts'; import { type GetContractReturnType, type HttpTransport, type PublicClient, getAddress, getContract } from 'viem'; import type * as chains from 'viem/chains'; -export class Watcher { +/** + * Represents a watcher for a rollup contract. + * + * It started on a network like anvil where time traveling is allowed, and auto-mine is turned on + * it will periodically check if the current slot have already been filled, e.g., there was an L2 + * block within the slot. And if so, it will time travel into the next slot. + */ +export class AnvilTestWatcher { private rollup: GetContractReturnType>; private filledRunningPromise?: RunningPromise; @@ -27,13 +34,24 @@ export class Watcher { this.logger.info(`Watcher created for rollup at ${rollupAddress}`); } - start() { + async start() { if (this.filledRunningPromise) { throw new Error('Watcher already watching for filled slot'); } - this.filledRunningPromise = new RunningPromise(() => this.mineIfSlotFilled(), 1000); - this.filledRunningPromise.start(); - this.logger.info(`Watcher started`); + + // If auto mining is not supported (e.g., we are on a real network), then we + // will simple do nothing. But if on an anvil or the like, this make sure that + // the sandbox and tests don't break because time is frozen and we never get to + // the next slot. + const isAutoMining = await this.cheatcodes.isAutoMining(); + + if (isAutoMining) { + this.filledRunningPromise = new RunningPromise(() => this.mineIfSlotFilled(), 1000); + this.filledRunningPromise.start(); + this.logger.info(`Watcher started`); + } else { + this.logger.info(`Watcher not started because not auto mining`); + } } async stop() { diff --git a/yarn-project/aztec.js/src/utils/cheat_codes.ts b/yarn-project/aztec.js/src/utils/cheat_codes.ts index 95d8d4710b3..f37e256ff7b 100644 --- a/yarn-project/aztec.js/src/utils/cheat_codes.ts +++ b/yarn-project/aztec.js/src/utils/cheat_codes.ts @@ -54,6 +54,20 @@ export class EthCheatCodes { return await (await fetch(this.rpcUrl, content)).json(); } + /** + * Get the auto mine status of the underlying chain + * @returns True if automine is on, false otherwise + */ + public async isAutoMining(): Promise { + try { + const res = await this.rpcCall('anvil_getAutomine', []); + return res.result; + } catch (err) { + this.logger.error(`Calling "anvil_getAutomine" failed with:`, err); + } + return false; + } + /** * Get the current blocknumber * @returns The current block number diff --git a/yarn-project/aztec.js/src/utils/index.ts b/yarn-project/aztec.js/src/utils/index.ts index 1a0a8236744..3fdc939fca1 100644 --- a/yarn-project/aztec.js/src/utils/index.ts +++ b/yarn-project/aztec.js/src/utils/index.ts @@ -5,3 +5,4 @@ export * from './cheat_codes.js'; export * from './authwit.js'; export * from './pxe.js'; export * from './account.js'; +export * from './anvil_test_watcher.js'; diff --git a/yarn-project/aztec.js/tsconfig.json b/yarn-project/aztec.js/tsconfig.json index 1d84c77d151..d404aff8c2f 100644 --- a/yarn-project/aztec.js/tsconfig.json +++ b/yarn-project/aztec.js/tsconfig.json @@ -18,6 +18,9 @@ { "path": "../foundation" }, + { + "path": "../l1-artifacts" + }, { "path": "../protocol-contracts" }, diff --git a/yarn-project/aztec/CHANGELOG.md b/yarn-project/aztec/CHANGELOG.md index 9bc19d34497..6b044257564 100644 --- a/yarn-project/aztec/CHANGELOG.md +++ b/yarn-project/aztec/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## [0.54.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.53.0...aztec-package-v0.54.0) (2024-09-10) + + +### Features + +* Archiver fork block num ([#8425](https://github.com/AztecProtocol/aztec-packages/issues/8425)) ([a9f2364](https://github.com/AztecProtocol/aztec-packages/commit/a9f2364264e5cba4d01f09ef18801dd5ff39ae87)) + + +### Miscellaneous + +* Merge devnet to master ([#8472](https://github.com/AztecProtocol/aztec-packages/issues/8472)) ([26706e9](https://github.com/AztecProtocol/aztec-packages/commit/26706e9d4339e6cf7603b6c86f1e7a1d3942bd63)) + +## [0.53.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.52.0...aztec-package-v0.53.0) (2024-09-09) + + +### Bug Fixes + +* Do not reuse anvil admin key ([#8304](https://github.com/AztecProtocol/aztec-packages/issues/8304)) ([6863fe5](https://github.com/AztecProtocol/aztec-packages/commit/6863fe5094193ce29118c8a315e38b7b3aea69ca)) +* Split stores per component and split merkle tree operations ([#8299](https://github.com/AztecProtocol/aztec-packages/issues/8299)) ([4ee69ac](https://github.com/AztecProtocol/aztec-packages/commit/4ee69acf8588adb46d2e9369d5541fb04380c652)) + + +### Miscellaneous + +* Change efs volumes to use bursting throughput ([#8370](https://github.com/AztecProtocol/aztec-packages/issues/8370)) ([d6ebe3e](https://github.com/AztecProtocol/aztec-packages/commit/d6ebe3e674ea59acf810c9736aa908c63b5a9b85)) +* Fix spartan test nightly runner ([#8433](https://github.com/AztecProtocol/aztec-packages/issues/8433)) ([a34f353](https://github.com/AztecProtocol/aztec-packages/commit/a34f35311ace0f06e22da111d72467dd976fdd8d)) +* Increase AZTEC_SLOT_DURATION ([#8331](https://github.com/AztecProtocol/aztec-packages/issues/8331)) ([5d48500](https://github.com/AztecProtocol/aztec-packages/commit/5d485006cf9fdf20b4081da1b203edf7abe1675f)) +* Merge provernet to master ([#8373](https://github.com/AztecProtocol/aztec-packages/issues/8373)) ([e1dc987](https://github.com/AztecProtocol/aztec-packages/commit/e1dc9878de06a1f3d4cde9bbcf652ac342951d52)) +* Pw/devnet fixes ([#8385](https://github.com/AztecProtocol/aztec-packages/issues/8385)) ([4fb4e17](https://github.com/AztecProtocol/aztec-packages/commit/4fb4e178d7cd6de999455b624ec4d3b6b63fceb7)) + ## [0.52.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.51.1...aztec-package-v0.52.0) (2024-09-01) diff --git a/yarn-project/aztec/package.json b/yarn-project/aztec/package.json index b986f0d167b..77a9c800110 100644 --- a/yarn-project/aztec/package.json +++ b/yarn-project/aztec/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/aztec", - "version": "0.52.0", + "version": "0.54.0", "type": "module", "exports": { ".": "./dest/index.js" diff --git a/yarn-project/aztec/src/bin/index.ts b/yarn-project/aztec/src/bin/index.ts index 65d2e284239..158543eb80b 100644 --- a/yarn-project/aztec/src/bin/index.ts +++ b/yarn-project/aztec/src/bin/index.ts @@ -41,5 +41,7 @@ async function main() { main().catch(err => { debugLogger.error(`Error in command execution`); debugLogger.error(err + '\n' + err.stack); - process.exit(1); + // See https://nodejs.org/api/process.html#processexitcode + process.exitCode = 1; + throw err; }); diff --git a/yarn-project/aztec/src/cli/cli.ts b/yarn-project/aztec/src/cli/cli.ts index fc8a0d226af..7dd198383ec 100644 --- a/yarn-project/aztec/src/cli/cli.ts +++ b/yarn-project/aztec/src/cli/cli.ts @@ -53,6 +53,7 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge const { aztecNodeConfig, node, pxe, stop } = await createSandbox({ enableGas: sandboxOptions.enableGas, l1Mnemonic: options.l1Mnemonic, + l1RpcUrl: options.l1RpcUrl, }); // Deploy test accounts by default diff --git a/yarn-project/aztec/src/sandbox.ts b/yarn-project/aztec/src/sandbox.ts index 8ba2f06256a..81e24a94856 100644 --- a/yarn-project/aztec/src/sandbox.ts +++ b/yarn-project/aztec/src/sandbox.ts @@ -1,6 +1,6 @@ #!/usr/bin/env -S node --no-warnings import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node'; -import { SignerlessWallet } from '@aztec/aztec.js'; +import { AnvilTestWatcher, EthCheatCodes, SignerlessWallet } from '@aztec/aztec.js'; import { DefaultMultiCallEntrypoint } from '@aztec/aztec.js/entrypoint'; import { type AztecNode } from '@aztec/circuit-types'; import { deployCanonicalAuthRegistry, deployCanonicalKeyRegistry, deployCanonicalL2FeeJuice } from '@aztec/cli/misc'; @@ -166,8 +166,25 @@ export async function createSandbox(config: Partial = {}) { aztecNodeConfig.validatorPrivateKey = `0x${Buffer.from(privKey!).toString('hex')}`; } + let watcher: AnvilTestWatcher | undefined = undefined; if (!aztecNodeConfig.p2pEnabled) { - await deployContractsToL1(aztecNodeConfig, hdAccount); + const l1ContractAddresses = await deployContractsToL1(aztecNodeConfig, hdAccount); + + const chain = aztecNodeConfig.l1RpcUrl + ? createEthereumChain(aztecNodeConfig.l1RpcUrl, aztecNodeConfig.l1ChainId) + : { chainInfo: localAnvil }; + + const publicClient = createPublicClient({ + chain: chain.chainInfo, + transport: httpViemTransport(aztecNodeConfig.l1RpcUrl), + }); + + watcher = new AnvilTestWatcher( + new EthCheatCodes(aztecNodeConfig.l1RpcUrl), + l1ContractAddresses.rollupAddress, + publicClient, + ); + await watcher.start(); } const client = await createAndStartTelemetryClient(getTelemetryClientConfig()); @@ -191,6 +208,7 @@ export async function createSandbox(config: Partial = {}) { const stop = async () => { await pxe.stop(); await node.stop(); + await watcher?.stop(); }; return { node, pxe, aztecNodeConfig, stop }; diff --git a/yarn-project/aztec/terraform/bot/main.tf b/yarn-project/aztec/terraform/bot/main.tf index 4dfe0641bf4..f49e44b334e 100644 --- a/yarn-project/aztec/terraform/bot/main.tf +++ b/yarn-project/aztec/terraform/bot/main.tf @@ -150,7 +150,7 @@ resource "aws_ecs_task_definition" "aztec-bot" { command = ["start", "--bot", "--pxe"] essential = true cpu = 8192 - memoryReservation = 14336 + memoryReservation = 15685 portMappings = [ { containerPort = 80 diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 6304b37ab45..4d684d4ed1b 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -126,14 +126,78 @@ resource "aws_efs_mount_target" "public_az2" { security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_public_id] } + +data "template_file" "user_data" { + count = local.node_count + template = <> /etc/ecs/ecs.config +echo 'ECS_INSTANCE_ATTRIBUTES={"group": "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}"}' >> /etc/ecs/ecs.config +EOF +} + +# Launch template for our prover agents +# 4 cores and 8 GB memory +resource "aws_launch_template" "aztec-node-launch-template" { + count = local.node_count + name = "${var.DEPLOY_TAG}-aztec-node-launch-template-${count.index + 1}" + image_id = "ami-0cd4858f2b923aa6b" + instance_type = "c6a.xlarge" + vpc_security_group_ids = [data.terraform_remote_state.setup_iac.outputs.security_group_private_id] + + iam_instance_profile { + name = data.terraform_remote_state.setup_iac.outputs.ecs_instance_profile_name + } + + key_name = data.terraform_remote_state.setup_iac.outputs.ecs_instance_key_pair_name + + user_data = base64encode(data.template_file.user_data[count.index].rendered) + + tag_specifications { + resource_type = "instance" + tags = { + Name = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" + prometheus = "" + } + } +} + +resource "aws_ec2_fleet" "aztec_node_fleet" { + count = local.node_count + launch_template_config { + launch_template_specification { + launch_template_id = aws_launch_template.aztec-node-launch-template[count.index].id + version = aws_launch_template.aztec-node-launch-template[count.index].latest_version + } + + override { + subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az1_private_id + availability_zone = "eu-west-2a" + } + + override { + subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az2_private_id + availability_zone = "eu-west-2b" + } + } + + target_capacity_specification { + default_target_capacity_type = "on-demand" + total_target_capacity = 1 + spot_target_capacity = 0 + on_demand_target_capacity = 1 + } + + terminate_instances = true + terminate_instances_with_expiration = true +} + # Define task definitions for each node. resource "aws_ecs_task_definition" "aztec-node" { count = local.node_count family = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" - requires_compatibilities = ["FARGATE"] + requires_compatibilities = ["EC2"] network_mode = "awsvpc" - cpu = "2048" - memory = "4096" execution_role_arn = data.terraform_remote_state.setup_iac.outputs.ecs_task_execution_role_arn task_role_arn = data.terraform_remote_state.aztec2_iac.outputs.cloudwatch_logging_ecs_role_arn @@ -151,7 +215,8 @@ resource "aws_ecs_task_definition" "aztec-node" { image = "${var.DOCKERHUB_ACCOUNT}/aztec:${var.IMAGE_TAG}" command = ["start", "--node", "--archiver", "--sequencer"] essential = true - memoryReservation = 3776 + cpu = 4096 + memoryReservation = 7790 portMappings = [ { containerPort = 80 @@ -202,6 +267,10 @@ resource "aws_ecs_task_definition" "aztec-node" { name = "ARCHIVER_POLLING_INTERVAL" value = "10000" }, + { + name = "ARCHIVER_L1_START_BLOCK", + value = "15918000" + }, { name = "SEQ_RETRY_INTERVAL" value = "10000" @@ -390,19 +459,20 @@ resource "aws_ecs_service" "aztec-node" { count = local.node_count name = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" cluster = data.terraform_remote_state.setup_iac.outputs.ecs_cluster_id - launch_type = "FARGATE" + launch_type = "EC2" desired_count = 1 deployment_maximum_percent = 100 deployment_minimum_healthy_percent = 0 - platform_version = "1.4.0" - force_new_deployment = true - enable_execute_command = true + #platform_version = "1.4.0" + force_new_deployment = true + enable_execute_command = true network_configuration { - assign_public_ip = true + #assign_public_ip = true subnets = [ - data.terraform_remote_state.setup_iac.outputs.subnet_az1_id + data.terraform_remote_state.setup_iac.outputs.subnet_az1_private_id, + data.terraform_remote_state.setup_iac.outputs.subnet_az2_private_id ] security_groups = [data.terraform_remote_state.aztec-network_iac.outputs.p2p_security_group_id, data.terraform_remote_state.setup_iac.outputs.security_group_private_id] } @@ -419,6 +489,11 @@ resource "aws_ecs_service" "aztec-node" { container_port = 80 } + placement_constraints { + type = "memberOf" + expression = "attribute:group == ${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" + } + task_definition = aws_ecs_task_definition.aztec-node[count.index].family } diff --git a/yarn-project/aztec/terraform/prover-node/main.tf b/yarn-project/aztec/terraform/prover-node/main.tf index 9ea84547ac0..21bbf2fe783 100644 --- a/yarn-project/aztec/terraform/prover-node/main.tf +++ b/yarn-project/aztec/terraform/prover-node/main.tf @@ -103,7 +103,7 @@ resource "aws_service_discovery_service" "aztec-prover-node" { # Configure an EFS filesystem. resource "aws_efs_file_system" "prover_node_data_store" { - creation_token = "${var.DEPLOY_TAG}-prover-node-data" + creation_token = "${var.DEPLOY_TAG}-prover-node-data" tags = { Name = "${var.DEPLOY_TAG}-prover-node-data" @@ -126,14 +126,77 @@ resource "aws_efs_mount_target" "public_az2" { security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_public_id] } +data "template_file" "user_data" { + count = local.node_count + template = <> /etc/ecs/ecs.config +echo 'ECS_INSTANCE_ATTRIBUTES={"group": "${var.DEPLOY_TAG}-prover-node-${count.index + 1}"}' >> /etc/ecs/ecs.config +EOF +} + +# Launch template for our prover agents +# 4 cores and 8 GB memory +resource "aws_launch_template" "aztec-prover-node-launch-template" { + count = local.node_count + name = "${var.DEPLOY_TAG}-prover-node-launch-template-${count.index + 1}" + image_id = "ami-0cd4858f2b923aa6b" + instance_type = "c6a.xlarge" + vpc_security_group_ids = [data.terraform_remote_state.setup_iac.outputs.security_group_private_id] + + iam_instance_profile { + name = data.terraform_remote_state.setup_iac.outputs.ecs_instance_profile_name + } + + key_name = data.terraform_remote_state.setup_iac.outputs.ecs_instance_key_pair_name + + user_data = base64encode(data.template_file.user_data[count.index].rendered) + + tag_specifications { + resource_type = "instance" + tags = { + Name = "${var.DEPLOY_TAG}-prover-node-${count.index + 1}" + prometheus = "" + } + } +} + +resource "aws_ec2_fleet" "aztec_prover_node_fleet" { + count = local.node_count + launch_template_config { + launch_template_specification { + launch_template_id = aws_launch_template.aztec-prover-node-launch-template[count.index].id + version = aws_launch_template.aztec-prover-node-launch-template[count.index].latest_version + } + + override { + subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az1_private_id + availability_zone = "eu-west-2a" + } + + override { + subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az2_private_id + availability_zone = "eu-west-2b" + } + } + + target_capacity_specification { + default_target_capacity_type = "on-demand" + total_target_capacity = 1 + spot_target_capacity = 0 + on_demand_target_capacity = 1 + } + + terminate_instances = true + terminate_instances_with_expiration = true +} + # Define task definitions for each node. resource "aws_ecs_task_definition" "aztec-prover-node" { count = local.node_count family = "${var.DEPLOY_TAG}-aztec-prover-node-${count.index + 1}" - requires_compatibilities = ["FARGATE"] + requires_compatibilities = ["EC2"] network_mode = "awsvpc" - cpu = "2048" - memory = "4096" execution_role_arn = data.terraform_remote_state.setup_iac.outputs.ecs_task_execution_role_arn task_role_arn = data.terraform_remote_state.aztec2_iac.outputs.cloudwatch_logging_ecs_role_arn @@ -151,7 +214,8 @@ resource "aws_ecs_task_definition" "aztec-prover-node" { image = "${var.DOCKERHUB_ACCOUNT}/aztec:${var.IMAGE_TAG}" command = ["start", "--prover-node", "--archiver"] essential = true - memoryReservation = 3776 + cpu = 4096 + memoryReservation = 7790 portMappings = [ { containerPort = 80 @@ -186,6 +250,7 @@ resource "aws_ecs_task_definition" "aztec-prover-node" { // Archiver { name = "ARCHIVER_POLLING_INTERVAL", value = "10000" }, + { name = "ARCHIVER_L1_START_BLOCK", value = "15918000" }, // Aztec node to pull clientivc proofs from (to be replaced with a p2p connection) { name = "TX_PROVIDER_NODE_URL", value = "http://${var.DEPLOY_TAG}-aztec-node-${count.index + 1}.local/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}/${var.API_KEY}" }, @@ -250,18 +315,19 @@ resource "aws_ecs_service" "aztec-prover-node" { count = local.node_count name = "${var.DEPLOY_TAG}-aztec-prover-node-${count.index + 1}" cluster = data.terraform_remote_state.setup_iac.outputs.ecs_cluster_id - launch_type = "FARGATE" + launch_type = "EC2" desired_count = 1 deployment_maximum_percent = 100 deployment_minimum_healthy_percent = 0 - platform_version = "1.4.0" - force_new_deployment = true - enable_execute_command = true + #platform_version = "1.4.0" + force_new_deployment = true + enable_execute_command = true network_configuration { - assign_public_ip = true + #assign_public_ip = true subnets = [ - data.terraform_remote_state.setup_iac.outputs.subnet_az1_id + data.terraform_remote_state.setup_iac.outputs.subnet_az1_private_id, + data.terraform_remote_state.setup_iac.outputs.subnet_az2_private_id ] security_groups = [data.terraform_remote_state.aztec-network_iac.outputs.p2p_security_group_id, data.terraform_remote_state.setup_iac.outputs.security_group_private_id] } @@ -278,6 +344,11 @@ resource "aws_ecs_service" "aztec-prover-node" { container_port = 80 } + placement_constraints { + type = "memberOf" + expression = "attribute:group == ${var.DEPLOY_TAG}-prover-node-${count.index + 1}" + } + task_definition = aws_ecs_task_definition.aztec-prover-node[count.index].family } diff --git a/yarn-project/aztec/terraform/prover/main.tf b/yarn-project/aztec/terraform/prover/main.tf index 537bc7e73f0..72b48ff520b 100644 --- a/yarn-project/aztec/terraform/prover/main.tf +++ b/yarn-project/aztec/terraform/prover/main.tf @@ -238,7 +238,7 @@ resource "aws_ecs_task_definition" "aztec-proving-agent" { "command": ["start", "--prover"], "essential": true, "cpu": 16384, - "memoryReservation": 122880, + "memoryReservation": 127800, "portMappings": [ { "containerPort": 80 @@ -285,9 +285,9 @@ resource "aws_ecs_task_definition" "aztec-proving-agent" { "name": "NETWORK_NAME", "value": "${var.DEPLOY_TAG}" }, - { - "name": "LOG_JSON", - "value": "1" + { + "name": "LOG_JSON", + "value": "1" } ], "logConfiguration": { diff --git a/yarn-project/bb-prover/package.json b/yarn-project/bb-prover/package.json index 37030d36b12..3fc9ae17d27 100644 --- a/yarn-project/bb-prover/package.json +++ b/yarn-project/bb-prover/package.json @@ -73,6 +73,7 @@ "tslib": "^2.4.0" }, "devDependencies": { + "@aztec/ethereum": "workspace:^", "@jest/globals": "^29.5.0", "@types/jest": "^29.5.0", "@types/memdown": "^3.0.0", @@ -81,7 +82,8 @@ "jest": "^29.5.0", "jest-mock-extended": "^3.0.3", "ts-node": "^10.9.1", - "typescript": "^5.0.4" + "typescript": "^5.0.4", + "viem": "^2.7.15" }, "files": [ "dest", diff --git a/yarn-project/bb-prover/src/bb/cli.ts b/yarn-project/bb-prover/src/bb/cli.ts index ca26dabb535..676882d8819 100644 --- a/yarn-project/bb-prover/src/bb/cli.ts +++ b/yarn-project/bb-prover/src/bb/cli.ts @@ -25,38 +25,6 @@ export function getProgram(log: LogFn): Command { log(Object.keys(ProtocolCircuitArtifacts).reduce((prev: string, x: string) => prev.concat(`\n${x}`))); }); - program - .command('write-pk') - .description('Generates the proving key for the specified circuit') - .requiredOption( - '-w, --working-directory ', - 'A directory to use for storing input/output files', - BB_WORKING_DIRECTORY, - ) - .requiredOption('-b, --bb-path ', 'The path to the BB binary', BB_BINARY_PATH) - .requiredOption('-c, --circuit ', 'The name of a protocol circuit') - .action(async options => { - const compiledCircuit = ProtocolCircuitArtifacts[options.circuit as ProtocolArtifact]; - if (!compiledCircuit) { - log(`Failed to find circuit ${options.circuit}`); - return; - } - try { - await fs.access(options.workingDirectory, fs.constants.W_OK); - } catch (error) { - log(`Working directory does not exist`); - return; - } - await generateKeyForNoirCircuit( - options.bbPath, - options.workingDirectory, - options.circuit, - compiledCircuit, - 'pk', - log, - ); - }); - program .command('write-vk') .description('Generates the verification key for the specified circuit') @@ -67,6 +35,7 @@ export function getProgram(log: LogFn): Command { ) .requiredOption('-b, --bb-path ', 'The path to the BB binary', BB_BINARY_PATH) .requiredOption('-c, --circuit ', 'The name of a protocol circuit') + .requiredOption('-f, --flavor ', 'The name of the verification key flavor', 'ultra_honk') .action(async options => { const compiledCircuit = ProtocolCircuitArtifacts[options.circuit as ProtocolArtifact]; if (!compiledCircuit) { @@ -84,7 +53,8 @@ export function getProgram(log: LogFn): Command { options.workingDirectory, options.circuit, compiledCircuit, - 'vk', + options.flavor, + // (options.circuit as ServerProtocolArtifact) === 'RootRollupArtifact' ? 'ultra_keccak_honk' : 'ultra_honk', log, ); }); diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index d48195e6b00..22c4b5e9393 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -8,6 +8,8 @@ import * as proc from 'child_process'; import * as fs from 'fs/promises'; import { basename, dirname, join } from 'path'; +import { type UltraHonkFlavor } from '../honk.js'; + export const VK_FILENAME = 'vk'; export const VK_FIELDS_FILENAME = 'vk_fields.json'; export const PROOF_FILENAME = 'proof'; @@ -113,7 +115,7 @@ export async function generateKeyForNoirCircuit( workingDirectory: string, circuitName: string, compiledCircuit: NoirCompiledCircuit, - key: 'vk' | 'pk', + flavor: UltraHonkFlavor, log: LogFn, force = false, ): Promise { @@ -123,7 +125,7 @@ export async function generateKeyForNoirCircuit( // The bytecode hash file is also written here as /workingDirectory/pk/BaseParityArtifact/bytecode-hash // The bytecode is written to e.g. /workingDirectory/pk/BaseParityArtifact/bytecode // The bytecode is removed after the key is generated, leaving just the hash file - const circuitOutputDirectory = `${workingDirectory}/${key}/${circuitName}`; + const circuitOutputDirectory = `${workingDirectory}/vk/${circuitName}`; const outputPath = `${circuitOutputDirectory}`; const bytecodeHash = sha256(bytecode); @@ -148,11 +150,11 @@ export async function generateKeyForNoirCircuit( // args are the output path and the input bytecode path const args = ['-o', `${outputPath}/${VK_FILENAME}`, '-b', bytecodePath]; const timer = new Timer(); - let result = await executeBB(pathToBB, `write_${key}_ultra_honk`, args, log); + let result = await executeBB(pathToBB, `write_vk_${flavor}`, args, log); // If we succeeded and the type of key if verification, have bb write the 'fields' version too - if (result.status == BB_RESULT.SUCCESS && key === 'vk') { + if (result.status == BB_RESULT.SUCCESS) { const asFieldsArgs = ['-k', `${outputPath}/${VK_FILENAME}`, '-o', `${outputPath}/${VK_FIELDS_FILENAME}`, '-v']; - result = await executeBB(pathToBB, `vk_as_fields_ultra_honk`, asFieldsArgs, log); + result = await executeBB(pathToBB, `vk_as_fields_${flavor}`, asFieldsArgs, log); } const duration = timer.ms(); @@ -160,8 +162,8 @@ export async function generateKeyForNoirCircuit( return { status: BB_RESULT.SUCCESS, durationMs: duration, - pkPath: key === 'pk' ? outputPath : undefined, - vkPath: key === 'vk' ? outputPath : undefined, + pkPath: undefined, + vkPath: outputPath, proofPath: undefined, }; } @@ -179,8 +181,8 @@ export async function generateKeyForNoirCircuit( return { status: BB_RESULT.ALREADY_PRESENT, durationMs: 0, - pkPath: key === 'pk' ? outputPath : undefined, - vkPath: key === 'vk' ? outputPath : undefined, + pkPath: undefined, + vkPath: outputPath, }; } @@ -261,6 +263,7 @@ export async function computeVerificationKey( workingDirectory: string, circuitName: string, bytecode: Buffer, + flavor: UltraHonkFlavor, log: LogFn, ): Promise { // Check that the working directory exists @@ -293,7 +296,7 @@ export async function computeVerificationKey( }; let result = await executeBB( pathToBB, - 'write_vk_ultra_honk', + `write_vk_${flavor}`, ['-o', outputPath, '-b', bytecodePath, '-v'], logFunction, ); @@ -302,7 +305,7 @@ export async function computeVerificationKey( } result = await executeBB( pathToBB, - 'vk_as_fields_ultra_honk', + `vk_as_fields_${flavor}`, ['-o', outputPath + '_fields.json', '-k', outputPath, '-v'], logFunction, ); @@ -343,6 +346,7 @@ export async function generateProof( circuitName: string, bytecode: Buffer, inputWitnessFile: string, + flavor: UltraHonkFlavor, log: LogFn, ): Promise { // Check that the working directory exists @@ -355,7 +359,7 @@ export async function generateProof( // The bytecode is written to e.g. /workingDirectory/BaseParityArtifact-bytecode const bytecodePath = `${workingDirectory}/${circuitName}-bytecode`; - // The proof is written to e.g. /workingDirectory/proof + // The proof is written to e.g. /workingDirectory/ultra_honk/proof const outputPath = `${workingDirectory}`; const binaryPresent = await fs @@ -374,7 +378,7 @@ export async function generateProof( const logFunction = (message: string) => { log(`${circuitName} BB out - ${message}`); }; - const result = await executeBB(pathToBB, 'prove_ultra_honk_output_all', args, logFunction); + const result = await executeBB(pathToBB, `prove_${flavor}_output_all`, args, logFunction); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { @@ -599,9 +603,10 @@ export async function verifyProof( pathToBB: string, proofFullPath: string, verificationKeyPath: string, + ultraHonkFlavor: UltraHonkFlavor, log: LogFn, ): Promise { - return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'verify_ultra_honk', log); + return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, `verify_${ultraHonkFlavor}`, log); } /** @@ -674,7 +679,7 @@ async function verifyProofInternal( pathToBB: string, proofFullPath: string, verificationKeyPath: string, - command: 'verify_ultra_honk' | 'avm_verify', + command: 'verify_ultra_honk' | 'verify_ultra_keccak_honk' | 'avm_verify', log: LogFn, ): Promise { const binaryPresent = await fs @@ -851,7 +856,7 @@ export async function generateContractForCircuit( workingDirectory, circuitName, compiledCircuit, - 'vk', + 'ultra_keccak_honk', log, force, ); diff --git a/yarn-project/bb-prover/src/honk.ts b/yarn-project/bb-prover/src/honk.ts new file mode 100644 index 00000000000..8c13ed14475 --- /dev/null +++ b/yarn-project/bb-prover/src/honk.ts @@ -0,0 +1,18 @@ +import { type ProtocolArtifact } from '@aztec/noir-protocol-circuits-types'; + +export type UltraHonkFlavor = 'ultra_honk' | 'ultra_keccak_honk'; + +const UltraKeccakHonkCircuits = ['BlockRootRollupArtifact'] as const; +type UltraKeccakHonkCircuits = (typeof UltraKeccakHonkCircuits)[number]; +type UltraHonkCircuits = Exclude; + +export function getUltraHonkFlavorForCircuit(artifact: UltraKeccakHonkCircuits): 'ultra_keccak_honk'; +export function getUltraHonkFlavorForCircuit(artifact: UltraHonkCircuits): 'ultra_honk'; +export function getUltraHonkFlavorForCircuit(artifact: ProtocolArtifact): UltraHonkFlavor; +export function getUltraHonkFlavorForCircuit(artifact: ProtocolArtifact): UltraHonkFlavor { + return isUltraKeccakHonkCircuit(artifact) ? 'ultra_keccak_honk' : 'ultra_honk'; +} + +function isUltraKeccakHonkCircuit(artifact: ProtocolArtifact): artifact is UltraKeccakHonkCircuits { + return UltraKeccakHonkCircuits.includes(artifact as UltraKeccakHonkCircuits); +} diff --git a/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts index 885eb37007a..52b26ba4535 100644 --- a/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts @@ -58,6 +58,7 @@ import { verifyProof, } from '../bb/execute.js'; import { type BBConfig } from '../config.js'; +import { type UltraHonkFlavor, getUltraHonkFlavorForCircuit } from '../honk.js'; import { mapProtocolArtifactNameToCircuitName } from '../stats.js'; import { extractVkData } from '../verification_key/verification_key_data.js'; @@ -213,7 +214,12 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver { this.log.debug(`${circuitType} BB out - ${message}`); }; - const result = await this.verifyProofFromKey(verificationKey.keyAsBytes, proof, logFunction); + const result = await this.verifyProofFromKey( + getUltraHonkFlavorForCircuit(circuitType), + verificationKey.keyAsBytes, + proof, + logFunction, + ); if (result.status === BB_RESULT.FAILURE) { const errorMessage = `Failed to verify ${circuitType} proof!`; @@ -224,6 +230,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver { } private async verifyProofFromKey( + flavor: UltraHonkFlavor, verificationKey: Buffer, proof: Proof, logFunction: (message: string) => void = () => {}, @@ -234,7 +241,7 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver { await fs.writeFile(proofFileName, proof.buffer); await fs.writeFile(verificationKeyPath, verificationKey); - return await verifyProof(this.bbBinaryPath, proofFileName, verificationKeyPath!, logFunction); + return await verifyProof(this.bbBinaryPath, proofFileName, verificationKeyPath!, flavor, logFunction); }; return await this.runInDirectory(operation); } @@ -301,7 +308,14 @@ export class BBNativePrivateKernelProver implements PrivateKernelProver { const timer = new Timer(); - const vkResult = await computeVerificationKey(this.bbBinaryPath, directory, circuitType, bytecode, this.log.debug); + const vkResult = await computeVerificationKey( + this.bbBinaryPath, + directory, + circuitType, + bytecode, + circuitType === 'App' ? 'ultra_honk' : getUltraHonkFlavorForCircuit(circuitType), + this.log.debug, + ); if (vkResult.status === BB_RESULT.FAILURE) { this.log.error(`Failed to generate proof for ${circuitType}${dbgCircuitName}: ${vkResult.reason}`); diff --git a/yarn-project/bb-prover/src/prover/bb_prover.ts b/yarn-project/bb-prover/src/prover/bb_prover.ts index 2c38db4869e..03a2bfa7929 100644 --- a/yarn-project/bb-prover/src/prover/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_prover.ts @@ -77,12 +77,12 @@ import * as fs from 'fs/promises'; import * as path from 'path'; import { + type BBFailure, type BBSuccess, BB_RESULT, PROOF_FIELDS_FILENAME, PROOF_FILENAME, VK_FILENAME, - type VerificationFunction, generateAvmProof, generateKeyForNoirCircuit, generateProof, @@ -92,6 +92,7 @@ import { writeProofAsFields, } from '../bb/execute.js'; import type { ACVMConfig, BBConfig } from '../config.js'; +import { type UltraHonkFlavor, getUltraHonkFlavorForCircuit } from '../honk.js'; import { ProverInstrumentation } from '../instrumentation.js'; import { PublicKernelArtifactMapping } from '../mappings/mappings.js'; import { mapProtocolArtifactNameToCircuitName } from '../stats.js'; @@ -99,11 +100,6 @@ import { extractAvmVkData, extractVkData } from '../verification_key/verificatio const logger = createDebugLogger('aztec:bb-prover'); -const CIRCUITS_WITHOUT_AGGREGATION: Set = new Set([ - 'BaseParityArtifact', - 'EmptyNestedArtifact', -]); - export interface BBProverConfig extends BBConfig, ACVMConfig { // list of circuits supported by this prover. defaults to all circuits if empty circuitFilter?: ServerProtocolArtifact[]; @@ -113,8 +109,8 @@ export interface BBProverConfig extends BBConfig, ACVMConfig { * Prover implementation that uses barretenberg native proving */ export class BBNativeRollupProver implements ServerCircuitProver { - private verificationKeys: Map> = new Map< - ServerProtocolArtifact, + private verificationKeys = new Map< + `ultra${'_keccak_' | '_'}honk_${ServerProtocolArtifact}`, Promise >(); @@ -235,6 +231,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { ); await this.verifyWithKey( + getUltraHonkFlavorForCircuit(kernelOps.artifact), kernelRequest.inputs.previousKernel.vk, kernelRequest.inputs.previousKernel.proof.binaryProof, ); @@ -539,6 +536,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { circuitType, Buffer.from(artifact.bytecode, 'base64'), outputWitnessFile, + getUltraHonkFlavorForCircuit(circuitType), logger.debug, ); @@ -682,9 +680,8 @@ export class BBNativeRollupProver implements ServerCircuitProver { this.instrumentation.recordSize('circuitSize', 'tubeCircuit', tubeVK.circuitSize); // Sanity check the tube proof (can be removed later) - await this.verifyWithKey(tubeVK, tubeProof.binaryProof); + await this.verifyWithKey('ultra_honk', tubeVK, tubeProof.binaryProof); - // TODO(#7369): properly time tube construction logger.info( `Generated proof for tubeCircuit in ${Math.ceil(provingResult.durationMs)} ms, size: ${ tubeProof.proof.length @@ -762,22 +759,25 @@ export class BBNativeRollupProver implements ServerCircuitProver { */ public async verifyProof(circuitType: ServerProtocolArtifact, proof: Proof) { const verificationKey = await this.getVerificationKeyDataForCircuit(circuitType); - // info(`vkey in: ${verificationKey.keyAsFields.key}`); - return await this.verifyWithKey(verificationKey, proof); + return await this.verifyWithKey(getUltraHonkFlavorForCircuit(circuitType), verificationKey, proof); } public async verifyAvmProof(proof: Proof, verificationKey: AvmVerificationKeyData) { - return await this.verifyWithKeyInternal(proof, verificationKey, verifyAvmProof); + return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) => + verifyAvmProof(this.config.bbBinaryPath, proofPath, vkPath, logger.debug), + ); } - public async verifyWithKey(verificationKey: VerificationKeyData, proof: Proof) { - return await this.verifyWithKeyInternal(proof, verificationKey, verifyProof); + public async verifyWithKey(flavor: UltraHonkFlavor, verificationKey: VerificationKeyData, proof: Proof) { + return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) => + verifyProof(this.config.bbBinaryPath, proofPath, vkPath, flavor, logger.debug), + ); } private async verifyWithKeyInternal( proof: Proof, verificationKey: { keyAsBytes: Buffer }, - verificationFunction: VerificationFunction, + verificationFunction: (proofPath: string, vkPath: string) => Promise, ) { const operation = async (bbWorkingDirectory: string) => { const proofFileName = path.join(bbWorkingDirectory, PROOF_FILENAME); @@ -786,16 +786,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { await fs.writeFile(proofFileName, proof.buffer); await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes); - const logFunction = (message: string) => { - logger.verbose(`BB out - ${message}`); - }; - - const result = await verificationFunction( - this.config.bbBinaryPath, - proofFileName, - verificationKeyPath!, - logFunction, - ); + const result = await verificationFunction(proofFileName, verificationKeyPath!); if (result.status === BB_RESULT.FAILURE) { const errorMessage = `Failed to verify proof from key!`; @@ -886,14 +877,15 @@ export class BBNativeRollupProver implements ServerCircuitProver { * @returns The verification key data */ private async getVerificationKeyDataForCircuit(circuitType: ServerProtocolArtifact): Promise { - let promise = this.verificationKeys.get(circuitType); + const flavor = getUltraHonkFlavorForCircuit(circuitType); + let promise = this.verificationKeys.get(`${flavor}_${circuitType}`); if (!promise) { promise = generateKeyForNoirCircuit( this.config.bbBinaryPath, this.config.bbWorkingDirectory, circuitType, ServerCircuitArtifacts[circuitType], - 'vk', + flavor, logger.debug, ).then(result => { if (result.status === BB_RESULT.FAILURE) { @@ -901,7 +893,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { } return extractVkData(result.vkPath!); }); - this.verificationKeys.set(circuitType, promise); + this.verificationKeys.set(`${flavor}_${circuitType}`, promise); } const vk = await promise; return vk.clone(); @@ -916,10 +908,11 @@ export class BBNativeRollupProver implements ServerCircuitProver { filePath: string, circuitType: ServerProtocolArtifact, ): Promise { - let promise = this.verificationKeys.get(circuitType); + const flavor = getUltraHonkFlavorForCircuit(circuitType); + let promise = this.verificationKeys.get(`${flavor}_${circuitType}`); if (!promise) { promise = extractVkData(filePath); - this.verificationKeys.set(circuitType, promise); + this.verificationKeys.set(`${flavor}_${circuitType}`, promise); } return promise; } @@ -943,20 +936,13 @@ export class BBNativeRollupProver implements ServerCircuitProver { fs.readFile(proofFieldsFilename, { encoding: 'utf-8' }), ]); const json = JSON.parse(proofString); - const vkData = await this.verificationKeys.get(circuitType); - if (!vkData) { - throw new Error(`Invalid verification key for ${circuitType}`); - } + const vkData = await this.getVerificationKeyDataForCircuit(circuitType); const numPublicInputs = vkData.numPublicInputs - AGGREGATION_OBJECT_LENGTH; const fieldsWithoutPublicInputs = json .slice(0, 3) .map(Fr.fromString) .concat(json.slice(3 + numPublicInputs).map(Fr.fromString)); - logger.debug( - `num pub inputs ${vkData.numPublicInputs} and without aggregation ${CIRCUITS_WITHOUT_AGGREGATION.has( - circuitType, - )}`, - ); + logger.debug(`num pub inputs ${vkData.numPublicInputs} circuit=${circuitType}`); const proof = new RecursiveProof( fieldsWithoutPublicInputs, diff --git a/yarn-project/bb-prover/src/verification_key/verification_key_data.ts b/yarn-project/bb-prover/src/verification_key/verification_key_data.ts index b5f4bacb1fa..908e49b5aee 100644 --- a/yarn-project/bb-prover/src/verification_key/verification_key_data.ts +++ b/yarn-project/bb-prover/src/verification_key/verification_key_data.ts @@ -3,11 +3,9 @@ import { AvmVerificationKeyAsFields, AvmVerificationKeyData, Fr, - VERIFICATION_KEY_LENGTH_IN_FIELDS, VerificationKeyAsFields, VerificationKeyData, } from '@aztec/circuits.js'; -import { type Tuple } from '@aztec/foundation/serialize'; import { strict as assert } from 'assert'; import * as fs from 'fs/promises'; @@ -29,10 +27,8 @@ export async function extractVkData(vkDirectoryPath: string): Promise, vkHash); - const vk = new VerificationKeyData(vkAsFields, rawBinary); - return vk; + const vkAsFields = new VerificationKeyAsFields(fields, vkHash); + return new VerificationKeyData(vkAsFields, rawBinary); } // TODO: This was adapted from the above function. A refactor might be needed. diff --git a/yarn-project/bb-prover/src/verifier/bb_verifier.ts b/yarn-project/bb-prover/src/verifier/bb_verifier.ts index 8cfc2688de1..55b16f1b846 100644 --- a/yarn-project/bb-prover/src/verifier/bb_verifier.ts +++ b/yarn-project/bb-prover/src/verifier/bb_verifier.ts @@ -22,6 +22,7 @@ import { verifyProof, } from '../bb/execute.js'; import { type BBConfig } from '../config.js'; +import { getUltraHonkFlavorForCircuit } from '../honk.js'; import { mapProtocolArtifactNameToCircuitName } from '../stats.js'; import { extractVkData } from '../verification_key/verification_key_data.js'; @@ -62,7 +63,7 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier { workingDirectory, circuit, ProtocolCircuitArtifacts[circuit], - 'vk', + getUltraHonkFlavorForCircuit(circuit), logFn, ).then(result => { if (result.status === BB_RESULT.FAILURE) { @@ -103,7 +104,13 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier { this.logger.debug(`${circuit} BB out - ${message}`); }; - const result = await verifyProof(this.config.bbBinaryPath, proofFileName, verificationKeyPath!, logFunction); + const result = await verifyProof( + this.config.bbBinaryPath, + proofFileName, + verificationKeyPath!, + getUltraHonkFlavorForCircuit(circuit), + logFunction, + ); if (result.status === BB_RESULT.FAILURE) { const errorMessage = `Failed to verify ${circuit} proof!`; diff --git a/yarn-project/bb-prover/tsconfig.json b/yarn-project/bb-prover/tsconfig.json index e0e59ed584c..77c9c6ff999 100644 --- a/yarn-project/bb-prover/tsconfig.json +++ b/yarn-project/bb-prover/tsconfig.json @@ -23,6 +23,9 @@ }, { "path": "../telemetry-client" + }, + { + "path": "../ethereum" } ], "include": ["src"] diff --git a/yarn-project/circuit-types/src/l2_block.ts b/yarn-project/circuit-types/src/l2_block.ts index efb61cd3e49..5f2fb4052b6 100644 --- a/yarn-project/circuit-types/src/l2_block.ts +++ b/yarn-project/circuit-types/src/l2_block.ts @@ -22,7 +22,6 @@ export class L2Block { /** * Constructs a new instance from named fields. * @param fields - Fields to pass to the constructor. - * @param blockHash - Hash of the block. * @returns A new instance. */ static fromFields(fields: { diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 989f1ce75e4..96be63148a3 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -88,7 +88,7 @@ export const INITIALIZATION_SLOT_SEPARATOR = 1000000000; export const INITIAL_L2_BLOCK_NUM = 1; export const BLOB_SIZE_IN_BYTES = 126976; export const ETHEREUM_SLOT_DURATION = 12; -export const AZTEC_SLOT_DURATION = 12; +export const AZTEC_SLOT_DURATION = 36; export const AZTEC_EPOCH_DURATION = 48; export const AZTEC_TARGET_COMMITTEE_SIZE = 48; export const GENESIS_ARCHIVE_ROOT = 8142738430000951296386584486068033372964809139261822027365426310856631083550n; @@ -258,11 +258,8 @@ export const AVM_CHAINID_BASE_L2_GAS = 200; export const AVM_VERSION_BASE_L2_GAS = 200; export const AVM_BLOCKNUMBER_BASE_L2_GAS = 200; export const AVM_TIMESTAMP_BASE_L2_GAS = 200; -export const AVM_COINBASE_BASE_L2_GAS = 200; export const AVM_FEEPERL2GAS_BASE_L2_GAS = 200; export const AVM_FEEPERDAGAS_BASE_L2_GAS = 200; -export const AVM_BLOCKL2GASLIMIT_BASE_L2_GAS = 200; -export const AVM_BLOCKDAGASLIMIT_BASE_L2_GAS = 200; export const AVM_CALLDATACOPY_BASE_L2_GAS = 290; export const AVM_L2GASLEFT_BASE_L2_GAS = 180; export const AVM_DAGASLEFT_BASE_L2_GAS = 180; @@ -323,11 +320,8 @@ export const AVM_CHAINID_DYN_L2_GAS = 0; export const AVM_VERSION_DYN_L2_GAS = 0; export const AVM_BLOCKNUMBER_DYN_L2_GAS = 0; export const AVM_TIMESTAMP_DYN_L2_GAS = 0; -export const AVM_COINBASE_DYN_L2_GAS = 0; export const AVM_FEEPERL2GAS_DYN_L2_GAS = 0; export const AVM_FEEPERDAGAS_DYN_L2_GAS = 0; -export const AVM_BLOCKL2GASLIMIT_DYN_L2_GAS = 0; -export const AVM_BLOCKDAGASLIMIT_DYN_L2_GAS = 0; export const AVM_CALLDATACOPY_DYN_L2_GAS = 50; export const AVM_L2GASLEFT_DYN_L2_GAS = 0; export const AVM_DAGASLEFT_DYN_L2_GAS = 0; diff --git a/yarn-project/circuits.js/src/hints/build_public_data_hints.test.ts b/yarn-project/circuits.js/src/hints/build_public_data_hints.test.ts index 3e038e13c9d..d88703a1d75 100644 --- a/yarn-project/circuits.js/src/hints/build_public_data_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_public_data_hints.test.ts @@ -1,4 +1,5 @@ import { makeTuple } from '@aztec/foundation/array'; +import { padArrayEnd } from '@aztec/foundation/collection'; import { Fr } from '@aztec/foundation/fields'; import { type Tuple } from '@aztec/foundation/serialize'; @@ -10,117 +11,106 @@ import { import { PublicDataRead, PublicDataTreeLeafPreimage, PublicDataUpdateRequest } from '../structs/index.js'; import { buildPublicDataHints } from './build_public_data_hints.js'; -class ExpectedHint { - constructor(public leafSlot: number, public value: number, public matchOrLowLeafSlot: number) {} - - static empty() { - return new ExpectedHint(0, 0, 0); - } - - toExpectedObject() { - return expect.objectContaining({ - leafSlot: new Fr(this.leafSlot), - value: new Fr(this.value), - leafPreimage: expect.objectContaining({ slot: new Fr(this.matchOrLowLeafSlot) }), - }); - } -} - describe('buildPublicDataHints', () => { let publicDataReads: Tuple; let publicDataUpdateRequests: Tuple; - let expectedHints: Tuple; - let sideEffectCounter = 0; - - const nextSideEffectCounter = () => sideEffectCounter++; const publicDataLeaves = [ - new PublicDataTreeLeafPreimage(new Fr(22), new Fr(200), new Fr(33), 0n), - new PublicDataTreeLeafPreimage(new Fr(11), new Fr(100), new Fr(22), 0n), - new PublicDataTreeLeafPreimage(new Fr(0), new Fr(0), new Fr(11), 0n), + new PublicDataTreeLeafPreimage(new Fr(0), new Fr(0), new Fr(11), 2n), + new PublicDataTreeLeafPreimage(new Fr(22), new Fr(200), new Fr(0), 0n), + new PublicDataTreeLeafPreimage(new Fr(11), new Fr(100), new Fr(22), 1n), ]; - const makePublicDataRead = (leafSlot: number, value: number) => new PublicDataRead(new Fr(leafSlot), new Fr(value)); + const makePublicDataRead = (leafSlot: number, value: number) => + new PublicDataRead(new Fr(leafSlot), new Fr(value), 0); const makePublicDataWrite = (leafSlot: number, value: number) => - new PublicDataUpdateRequest(new Fr(leafSlot), new Fr(value), nextSideEffectCounter()); + new PublicDataUpdateRequest(new Fr(leafSlot), new Fr(value), 0); const oracle = { getMatchOrLowPublicDataMembershipWitness: (leafSlot: bigint) => { - const leafPreimage = publicDataLeaves.find(l => l.slot.toBigInt() <= leafSlot); + const leafPreimage = publicDataLeaves.find( + l => l.slot.toBigInt() <= leafSlot && (l.nextSlot.isZero() || l.nextSlot.toBigInt() > leafSlot), + ); return { membershipWitness: {}, leafPreimage } as any; }, }; - const buildHints = () => buildPublicDataHints(oracle, publicDataReads, publicDataUpdateRequests); - - const buildAndCheckHints = async () => { - const hints = await buildHints(); - const partialHints = expectedHints.map(h => h.toExpectedObject()); - expect(hints).toEqual(partialHints); + const buildAndCheckHints = async (expectedSlots: number[]) => { + const hints = await buildPublicDataHints(oracle, publicDataReads, publicDataUpdateRequests); + const partialHints = expectedSlots.map(s => + expect.objectContaining({ + preimage: publicDataLeaves.find(l => l.slot.equals(new Fr(s))), + }), + ); + const emptyPartialHint = expect.objectContaining({ preimage: PublicDataTreeLeafPreimage.empty() }); + expect(hints).toEqual(padArrayEnd(partialHints, emptyPartialHint, MAX_PUBLIC_DATA_HINTS)); }; beforeEach(() => { publicDataReads = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty); publicDataUpdateRequests = makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest.empty); - expectedHints = makeTuple(MAX_PUBLIC_DATA_HINTS, ExpectedHint.empty); }); it('returns empty hints', async () => { - await buildAndCheckHints(); + await buildAndCheckHints([]); }); it('builds hints for reads for uninitialized slots', async () => { publicDataReads[0] = makePublicDataRead(12, 0); publicDataReads[1] = makePublicDataRead(39, 0); - expectedHints[0] = new ExpectedHint(12, 0, 11); - expectedHints[1] = new ExpectedHint(39, 0, 22); - - await buildAndCheckHints(); + await buildAndCheckHints([11, 22]); }); it('builds hints for reads for initialized slots', async () => { publicDataReads[0] = makePublicDataRead(22, 200); publicDataReads[1] = makePublicDataRead(11, 100); - expectedHints[0] = new ExpectedHint(22, 200, 22); - expectedHints[1] = new ExpectedHint(11, 100, 11); - - await buildAndCheckHints(); + await buildAndCheckHints([22, 11]); }); it('builds hints for writes to uninitialized slots', async () => { publicDataUpdateRequests[0] = makePublicDataWrite(5, 500); publicDataUpdateRequests[1] = makePublicDataWrite(17, 700); - expectedHints[0] = new ExpectedHint(5, 0, 0); - expectedHints[1] = new ExpectedHint(17, 0, 11); - - await buildAndCheckHints(); + await buildAndCheckHints([0, 11]); }); it('builds hints for writes to initialized slots', async () => { publicDataUpdateRequests[0] = makePublicDataWrite(11, 111); publicDataUpdateRequests[1] = makePublicDataWrite(22, 222); - expectedHints[0] = new ExpectedHint(11, 100, 11); - expectedHints[1] = new ExpectedHint(22, 200, 22); + await buildAndCheckHints([11, 22]); + }); - await buildAndCheckHints(); + it('skip hints for repeated reads', async () => { + publicDataReads[0] = makePublicDataRead(22, 200); // 22 + publicDataReads[1] = makePublicDataRead(39, 0); // 22 + publicDataReads[2] = makePublicDataRead(22, 200); // No hint needed because slot 22 was read. + publicDataReads[3] = makePublicDataRead(39, 0); // No hint needed because slot 39 was read. + publicDataReads[4] = makePublicDataRead(12, 0); // 11 + publicDataReads[5] = makePublicDataRead(39, 0); // // No hint needed because slot 39 was read. + await buildAndCheckHints([22, 22, 11]); }); - it('builds hints for mixed reads and writes', async () => { - publicDataReads[0] = makePublicDataRead(22, 200); - publicDataReads[1] = makePublicDataRead(12, 0); - publicDataReads[2] = makePublicDataRead(39, 0); - publicDataReads[3] = makePublicDataRead(11, 100); - publicDataUpdateRequests[0] = makePublicDataWrite(11, 111); - publicDataUpdateRequests[1] = makePublicDataWrite(5, 500); - publicDataUpdateRequests[2] = makePublicDataWrite(17, 700); - publicDataUpdateRequests[3] = makePublicDataWrite(22, 222); - expectedHints[0] = new ExpectedHint(22, 200, 22); - expectedHints[1] = new ExpectedHint(12, 0, 11); - expectedHints[2] = new ExpectedHint(39, 0, 22); - expectedHints[3] = new ExpectedHint(11, 100, 11); - expectedHints[4] = new ExpectedHint(5, 0, 0); - expectedHints[5] = new ExpectedHint(17, 0, 11); + it('skip hints for repeated writes', async () => { + publicDataUpdateRequests[0] = makePublicDataWrite(11, 111); // 11 + publicDataUpdateRequests[1] = makePublicDataWrite(5, 500); // 0 + publicDataUpdateRequests[2] = makePublicDataWrite(11, 112); // No hint needed because slot 11 was written. + publicDataUpdateRequests[3] = makePublicDataWrite(17, 700); // 11 + publicDataUpdateRequests[4] = makePublicDataWrite(11, 113); // No hint needed because slot 11 was written. + publicDataUpdateRequests[5] = makePublicDataWrite(5, 222); // No hint needed because slot 5 was written. + publicDataUpdateRequests[6] = makePublicDataWrite(37, 700); // 22 + await buildAndCheckHints([11, 0, 11, 22]); + }); - await buildAndCheckHints(); + it('builds hints for mixed reads and writes', async () => { + publicDataReads[0] = makePublicDataRead(22, 200); // 22 + publicDataReads[1] = makePublicDataRead(7, 0); // 0 + publicDataReads[2] = makePublicDataRead(41, 0); // 22 + publicDataReads[3] = makePublicDataRead(11, 100); // 11 + publicDataReads[4] = makePublicDataRead(39, 0); // 22 + publicDataUpdateRequests[0] = makePublicDataWrite(11, 111); // No hint needed because slot 11 was read. + publicDataUpdateRequests[1] = makePublicDataWrite(5, 500); // 0 + publicDataUpdateRequests[2] = makePublicDataWrite(17, 700); // 11 + publicDataUpdateRequests[3] = makePublicDataWrite(22, 222); // No hint needed because slot 22 was read. + publicDataUpdateRequests[4] = makePublicDataWrite(39, 700); // No hint needed because slot 39 was read. + await buildAndCheckHints([22, 0, 22, 11, 22, 0, 11]); }); }); diff --git a/yarn-project/circuits.js/src/hints/build_public_data_hints.ts b/yarn-project/circuits.js/src/hints/build_public_data_hints.ts index 940848ae82e..53200bab364 100644 --- a/yarn-project/circuits.js/src/hints/build_public_data_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_public_data_hints.ts @@ -9,6 +9,7 @@ import { type PUBLIC_DATA_TREE_HEIGHT, } from '../constants.gen.js'; import { + PublicDataLeafHint, type PublicDataRead, type PublicDataTreeLeafPreimage, type PublicDataUpdateRequest, @@ -25,18 +26,22 @@ type PublicDataMembershipWitnessOracle = { getMatchOrLowPublicDataMembershipWitness(leafSlot: bigint): Promise; }; +async function buildPublicDataLeafHint(oracle: PublicDataMembershipWitnessOracle, leafSlot: bigint) { + const { membershipWitness, leafPreimage } = await oracle.getMatchOrLowPublicDataMembershipWitness(leafSlot); + return new PublicDataLeafHint(leafPreimage, membershipWitness); +} + export async function buildPublicDataHints( oracle: PublicDataMembershipWitnessOracle, publicDataReads: Tuple, publicDataUpdateRequests: Tuple, -): Promise> { - const publicDataLeafSlots = [...publicDataReads, ...publicDataUpdateRequests] - .filter(r => !r.isEmpty()) - .map(r => r.leafSlot.toBigInt()); - const uniquePublicDataLeafSlots = [...new Set(publicDataLeafSlots)]; - - const hints = await Promise.all(uniquePublicDataLeafSlots.map(slot => buildPublicDataHint(oracle, slot))); - return padArrayEnd(hints, PublicDataHint.empty(), MAX_PUBLIC_DATA_HINTS); +): Promise> { + const leafSlots = [...publicDataReads.map(r => r.leafSlot), ...publicDataUpdateRequests.map(w => w.leafSlot)] + .filter(s => !s.isZero()) + .map(s => s.toBigInt()); + const uniqueLeafSlots = [...new Set(leafSlots)]; + const hints = await Promise.all(uniqueLeafSlots.map(slot => buildPublicDataLeafHint(oracle, slot))); + return padArrayEnd(hints, PublicDataLeafHint.empty(), MAX_PUBLIC_DATA_HINTS); } export async function buildPublicDataHint(oracle: PublicDataMembershipWitnessOracle, leafSlot: bigint) { diff --git a/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.test.ts deleted file mode 100644 index 4afea4a13b9..00000000000 --- a/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.test.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { makeTuple } from '@aztec/foundation/array'; -import { padArrayEnd } from '@aztec/foundation/collection'; -import { Fr } from '@aztec/foundation/fields'; -import { type Tuple } from '@aztec/foundation/serialize'; - -import { - MAX_PUBLIC_DATA_HINTS, - MAX_PUBLIC_DATA_READS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, -} from '../constants.gen.js'; -import { - LeafDataReadHint, - PendingReadHint, - PublicDataHint, - PublicDataRead, - PublicDataUpdateRequest, - ReadRequestStatus, -} from '../structs/index.js'; -import { buildPublicDataReadRequestHints } from './build_public_data_read_request_hints.js'; - -describe('buildPublicDataReadRequestHints', () => { - let publicDataReads: Tuple; - let expectedStatuses: Tuple; - let expectedPendingHints: Tuple; - let expectedLeafDataHints: Tuple; - let counter = 0; - const nextCounter = () => counter++; - - const makePublicDataWrite = (leafSlot: number, value: number) => - new PublicDataUpdateRequest(new Fr(leafSlot), new Fr(value), nextCounter()); - const makePublicDataHint = (slot: number, value: number) => { - const hint = PublicDataHint.empty(); - hint.leafSlot = new Fr(slot); - hint.value = new Fr(value); - return hint; - }; - const makePublicDataRead = (leafSlot: number, value: number) => new PublicDataRead(new Fr(leafSlot), new Fr(value)); - const makePendingHint = (readRequestIndex: number, hintIndex: number) => - new PendingReadHint(readRequestIndex, hintIndex); - const makeLeafDataHint = (readRequestIndex: number, hintIndex: number) => - new LeafDataReadHint(readRequestIndex, hintIndex); - - const publicDataUpdateRequests = padArrayEnd( - [makePublicDataWrite(55, 5555), makePublicDataWrite(77, 7777), makePublicDataWrite(99, 9999)], - PublicDataUpdateRequest.empty(), - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - ); - - const publicDataHints = padArrayEnd( - [ - makePublicDataHint(11, 100), - makePublicDataHint(22, 200), - makePublicDataHint(33, 300), - makePublicDataHint(55, 500), - makePublicDataHint(77, 0), - makePublicDataHint(99, 900), - ], - PublicDataHint.empty(), - MAX_PUBLIC_DATA_HINTS, - ); - - const buildHints = () => buildPublicDataReadRequestHints(publicDataReads, publicDataUpdateRequests, publicDataHints); - - const buildAndCheckHints = () => { - const hints = buildHints(); - expect(hints.readRequestStatuses).toEqual(expectedStatuses); - expect(hints.pendingReadHints).toEqual(expectedPendingHints); - expect(hints.leafDataReadHints).toEqual(expectedLeafDataHints); - }; - - beforeEach(() => { - publicDataReads = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty); - expectedStatuses = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, ReadRequestStatus.nada); - expectedPendingHints = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, () => - PendingReadHint.nada(MAX_PUBLIC_DATA_READS_PER_TX), - ); - expectedLeafDataHints = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, () => - LeafDataReadHint.nada(MAX_PUBLIC_DATA_READS_PER_TX), - ); - }); - - it('returns empty hints', () => { - buildAndCheckHints(); - }); - - it('builds hints for reading pending values', () => { - publicDataReads[0] = makePublicDataRead(77, 7777); - publicDataReads[1] = makePublicDataRead(99, 9999); - publicDataReads[2] = makePublicDataRead(55, 5555); - expectedStatuses[0] = ReadRequestStatus.pending(0); - expectedStatuses[1] = ReadRequestStatus.pending(1); - expectedStatuses[2] = ReadRequestStatus.pending(2); - expectedPendingHints[0] = makePendingHint(0, 1); - expectedPendingHints[1] = makePendingHint(1, 2); - expectedPendingHints[2] = makePendingHint(2, 0); - - buildAndCheckHints(); - }); - - it('builds hints for reading settled or uninitialized values', () => { - publicDataReads[0] = makePublicDataRead(33, 300); - publicDataReads[1] = makePublicDataRead(77, 0); - publicDataReads[2] = makePublicDataRead(55, 500); - publicDataReads[3] = makePublicDataRead(11, 100); - expectedStatuses[0] = ReadRequestStatus.settled(0); - expectedStatuses[1] = ReadRequestStatus.settled(1); - expectedStatuses[2] = ReadRequestStatus.settled(2); - expectedStatuses[3] = ReadRequestStatus.settled(3); - expectedLeafDataHints[0] = makeLeafDataHint(0, 2); - expectedLeafDataHints[1] = makeLeafDataHint(1, 4); - expectedLeafDataHints[2] = makeLeafDataHint(2, 3); - expectedLeafDataHints[3] = makeLeafDataHint(3, 0); - - buildAndCheckHints(); - }); - - it('builds hints for reading pending and settled values', () => { - publicDataReads[0] = makePublicDataRead(55, 500); - publicDataReads[1] = makePublicDataRead(55, 5555); - publicDataReads[2] = makePublicDataRead(77, 0); - publicDataReads[3] = makePublicDataRead(11, 100); - publicDataReads[4] = makePublicDataRead(99, 9999); - publicDataReads[5] = makePublicDataRead(77, 7777); - publicDataReads[6] = makePublicDataRead(11, 100); - expectedStatuses[0] = ReadRequestStatus.settled(0); - expectedStatuses[1] = ReadRequestStatus.pending(0); - expectedStatuses[2] = ReadRequestStatus.settled(1); - expectedStatuses[3] = ReadRequestStatus.settled(2); - expectedStatuses[4] = ReadRequestStatus.pending(1); - expectedStatuses[5] = ReadRequestStatus.pending(2); - expectedStatuses[6] = ReadRequestStatus.settled(3); - expectedPendingHints[0] = makePendingHint(1, 0); - expectedPendingHints[1] = makePendingHint(4, 2); - expectedPendingHints[2] = makePendingHint(5, 1); - expectedLeafDataHints[0] = makeLeafDataHint(0, 3); - expectedLeafDataHints[1] = makeLeafDataHint(2, 4); - expectedLeafDataHints[2] = makeLeafDataHint(3, 0); - expectedLeafDataHints[3] = makeLeafDataHint(6, 0); - - buildAndCheckHints(); - }); - - it('throws if reading unknown slot', () => { - publicDataReads[0] = makePublicDataRead(123, 100); - expect(() => buildHints()).toThrow('Cannot find a pending write or a data hint for the read request.'); - }); - - it('throws if reading unknown value', () => { - publicDataReads[0] = makePublicDataRead(11, 1111); - expect(() => buildHints()).toThrow('Value being read does not match existing public data or pending writes.'); - }); -}); diff --git a/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.ts b/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.ts deleted file mode 100644 index 4f7b15f312b..00000000000 --- a/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { type Tuple } from '@aztec/foundation/serialize'; - -import { - type MAX_PUBLIC_DATA_HINTS, - type MAX_PUBLIC_DATA_READS_PER_TX, - type MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, -} from '../constants.gen.js'; -import { - type PublicDataRead, - PublicDataReadRequestHintsBuilder, - type PublicDataUpdateRequest, -} from '../structs/index.js'; -import { type PublicDataHint } from '../structs/public_data_hint.js'; -import { countAccumulatedItems } from '../utils/index.js'; - -export function buildPublicDataReadRequestHints( - publicDataReads: Tuple, - publicDataUpdateRequests: Tuple, - publicDataHints: Tuple, -) { - const builder = new PublicDataReadRequestHintsBuilder(); - - const numReadRequests = countAccumulatedItems(publicDataReads); - for (let i = 0; i < numReadRequests; ++i) { - const rr = publicDataReads[i]; - // TODO: Add counters to reads and writes. - const writeIndex = publicDataUpdateRequests.findIndex( - w => w.leafSlot.equals(rr.leafSlot) && w.newValue.equals(rr.value), - ); - if (writeIndex !== -1) { - builder.addPendingReadRequest(i, writeIndex); - } else { - const hintIndex = publicDataHints.findIndex(h => h.leafSlot.equals(rr.leafSlot)); - if (hintIndex === -1) { - throw new Error('Cannot find a pending write or a data hint for the read request.'); - } - if (!publicDataHints[hintIndex].value.equals(rr.value)) { - throw new Error('Value being read does not match existing public data or pending writes.'); - } - builder.addLeafDataReadRequest(i, hintIndex); - } - } - - return builder.toHints(); -} diff --git a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts index ab4a63ba807..a4c0c921638 100644 --- a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts @@ -1,6 +1,7 @@ +import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { Fr } from '@aztec/foundation/fields'; + import { - AztecAddress, - Fr, NoteHash, Nullifier, ReadRequest, @@ -8,8 +9,7 @@ import { type ScopedNullifier, ScopedReadRequest, TransientDataIndexHint, -} from '@aztec/circuits.js'; - +} from '../structs/index.js'; import { buildTransientDataHints } from './build_transient_data_hints.js'; describe('buildTransientDataHints', () => { diff --git a/yarn-project/circuits.js/src/hints/index.ts b/yarn-project/circuits.js/src/hints/index.ts index 92b57bd25e1..67970d7bdc4 100644 --- a/yarn-project/circuits.js/src/hints/index.ts +++ b/yarn-project/circuits.js/src/hints/index.ts @@ -2,5 +2,4 @@ export * from './build_note_hash_read_request_hints.js'; export * from './build_nullifier_non_existent_read_request_hints.js'; export * from './build_nullifier_read_request_hints.js'; export * from './build_public_data_hints.js'; -export * from './build_public_data_read_request_hints.js'; export * from './build_transient_data_hints.js'; diff --git a/yarn-project/circuits.js/src/scripts/constants.in.ts b/yarn-project/circuits.js/src/scripts/constants.in.ts index d2e7f347643..819f7da934f 100644 --- a/yarn-project/circuits.js/src/scripts/constants.in.ts +++ b/yarn-project/circuits.js/src/scripts/constants.in.ts @@ -64,7 +64,6 @@ const CPP_CONSTANTS = [ 'VERSION_SELECTOR', 'BLOCK_NUMBER_SELECTOR', 'TIMESTAMP_SELECTOR', - 'COINBASE_SELECTOR', 'FEE_PER_DA_GAS_SELECTOR', 'FEE_PER_L2_GAS_SELECTOR', 'END_GLOBAL_VARIABLES', @@ -103,7 +102,6 @@ const PIL_CONSTANTS = [ 'VERSION_SELECTOR', 'BLOCK_NUMBER_SELECTOR', 'TIMESTAMP_SELECTOR', - 'COINBASE_SELECTOR', 'FEE_PER_DA_GAS_SELECTOR', 'FEE_PER_L2_GAS_SELECTOR', 'END_GLOBAL_VARIABLES', diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 19cb59bdeec..fdc31489a7a 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -60,8 +60,8 @@ export * from './public_call_stack_item.js'; export * from './public_call_stack_item_compressed.js'; export * from './public_circuit_public_inputs.js'; export * from './public_data_hint.js'; -export * from './public_data_read_request.js'; -export * from './public_data_read_request_hints.js'; +export * from './public_data_leaf_hint.js'; +export * from './public_data_read.js'; export * from './public_data_update_request.js'; export * from './public_validation_requests.js'; export * from './read_request.js'; diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts index 7c2be1c3da5..c0bb9b4d82f 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts @@ -13,8 +13,7 @@ import { nullifierNonExistentReadRequestHintsFromBuffer, } from '../non_existent_read_request_hints.js'; import { PartialStateReference } from '../partial_state_reference.js'; -import { PublicDataHint } from '../public_data_hint.js'; -import { PublicDataReadRequestHints } from '../public_data_read_request_hints.js'; +import { PublicDataLeafHint } from '../public_data_leaf_hint.js'; import { type NullifierReadRequestHints, nullifierReadRequestHintsFromBuffer } from '../read_request_hints/index.js'; import { TreeLeafReadRequestHint } from '../tree_leaf_read_request_hint.js'; import { PublicKernelData } from './public_kernel_data.js'; @@ -44,8 +43,7 @@ export class PublicKernelTailCircuitPrivateInputs { TreeLeafReadRequestHint, typeof MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX >, - public readonly publicDataHints: Tuple, - public readonly publicDataReadRequestHints: PublicDataReadRequestHints, + public readonly publicDataHints: Tuple, public readonly startState: PartialStateReference, ) {} @@ -57,7 +55,6 @@ export class PublicKernelTailCircuitPrivateInputs { this.nullifierNonExistentReadRequestHints, this.l1ToL2MsgReadRequestHints, this.publicDataHints, - this.publicDataReadRequestHints, this.startState, ); } @@ -86,8 +83,7 @@ export class PublicKernelTailCircuitPrivateInputs { reader.readArray(MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, { fromBuffer: buf => TreeLeafReadRequestHint.fromBuffer(buf, L1_TO_L2_MSG_TREE_HEIGHT), }), - reader.readArray(MAX_PUBLIC_DATA_HINTS, PublicDataHint), - reader.readObject(PublicDataReadRequestHints), + reader.readArray(MAX_PUBLIC_DATA_HINTS, PublicDataLeafHint), reader.readObject(PartialStateReference), ); } diff --git a/yarn-project/circuits.js/src/structs/proof.ts b/yarn-project/circuits.js/src/structs/proof.ts index 1ccfe85ce09..298210cc551 100644 --- a/yarn-project/circuits.js/src/structs/proof.ts +++ b/yarn-project/circuits.js/src/structs/proof.ts @@ -1,6 +1,8 @@ -import { Fr } from '@aztec/bb.js'; +import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { AGGREGATION_OBJECT_LENGTH } from '../constants.gen.js'; + const EMPTY_PROOF_SIZE = 42; /** @@ -12,6 +14,14 @@ const EMPTY_PROOF_SIZE = 42; export class Proof { // Make sure this type is not confused with other buffer wrappers readonly __proofBrand: any; + + // Honk proofs start with a 4 byte length prefix + // the proof metadata starts immediately after + private readonly metadataOffset = 4; + // the metadata is 3 Frs long + // the public inputs are after it + private readonly publicInputsOffset = 100; + constructor( /** * Holds the serialized proof data in a binary buffer format. @@ -55,11 +65,22 @@ export class Proof { } public withoutPublicInputs(): Buffer { - if (this.numPublicInputs > 0) { - return this.buffer.subarray(Fr.SIZE_IN_BYTES * this.numPublicInputs); - } else { - return this.buffer; - } + return Buffer.concat([ + this.buffer.subarray(this.metadataOffset, this.publicInputsOffset), + this.buffer.subarray(this.publicInputsOffset + Fr.SIZE_IN_BYTES * this.numPublicInputs), + ]); + } + + public extractPublicInputs(): Fr[] { + const reader = BufferReader.asReader( + this.buffer.subarray(this.publicInputsOffset, this.publicInputsOffset + Fr.SIZE_IN_BYTES * this.numPublicInputs), + ); + return reader.readArray(this.numPublicInputs, Fr); + } + + public extractAggregationObject(): Fr[] { + const publicInputs = this.extractPublicInputs(); + return publicInputs.slice(-1 * AGGREGATION_OBJECT_LENGTH); } /** diff --git a/yarn-project/circuits.js/src/structs/public_data_leaf_hint.ts b/yarn-project/circuits.js/src/structs/public_data_leaf_hint.ts new file mode 100644 index 00000000000..aba7c583e37 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/public_data_leaf_hint.ts @@ -0,0 +1,28 @@ +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { PUBLIC_DATA_TREE_HEIGHT } from '../constants.gen.js'; +import { MembershipWitness } from './membership_witness.js'; +import { PublicDataTreeLeafPreimage } from './trees/index.js'; + +export class PublicDataLeafHint { + constructor( + public preimage: PublicDataTreeLeafPreimage, + public membershipWitness: MembershipWitness, + ) {} + + static empty() { + return new PublicDataLeafHint(PublicDataTreeLeafPreimage.empty(), MembershipWitness.empty(PUBLIC_DATA_TREE_HEIGHT)); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PublicDataLeafHint( + reader.readObject(PublicDataTreeLeafPreimage), + MembershipWitness.fromBuffer(reader, PUBLIC_DATA_TREE_HEIGHT), + ); + } + + toBuffer() { + return serializeToBuffer(this.preimage, this.membershipWitness); + } +} diff --git a/yarn-project/circuits.js/src/structs/public_data_read_request.ts b/yarn-project/circuits.js/src/structs/public_data_read.ts similarity index 56% rename from yarn-project/circuits.js/src/structs/public_data_read_request.ts rename to yarn-project/circuits.js/src/structs/public_data_read.ts index 4244f93ff9e..e5a8010fd7e 100644 --- a/yarn-project/circuits.js/src/structs/public_data_read_request.ts +++ b/yarn-project/circuits.js/src/structs/public_data_read.ts @@ -1,7 +1,6 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; -// TODO: Rename to PublicDataReadRequest /** * Read operations from the public state tree. */ @@ -16,51 +15,34 @@ export class PublicDataRead { */ public readonly value: Fr, /** - * Optional side effect counter tracking position of this event in tx execution. + * Side effect counter tracking position of this event in tx execution. */ - public readonly sideEffectCounter?: number, + public readonly counter: number, ) {} - static from(args: { - /** - * Index of the leaf in the public data tree. - */ - leafIndex: Fr; - /** - * Returned value from the public data tree. - */ - value: Fr; - }) { - return new PublicDataRead(args.leafIndex, args.value); - } - toBuffer() { - return serializeToBuffer(this.leafSlot, this.value); + return serializeToBuffer(this.leafSlot, this.value, this.counter); } isEmpty() { - return this.leafSlot.isZero() && this.value.isZero(); + return this.leafSlot.isZero() && this.value.isZero() && !this.counter; } static fromFields(fields: Fr[] | FieldReader) { const reader = FieldReader.asReader(fields); - return new PublicDataRead(reader.readField(), reader.readField()); + return new PublicDataRead(reader.readField(), reader.readField(), reader.readU32()); } static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new PublicDataRead(Fr.fromBuffer(reader), Fr.fromBuffer(reader)); + return new PublicDataRead(Fr.fromBuffer(reader), Fr.fromBuffer(reader), reader.readNumber()); } static empty() { - return new PublicDataRead(Fr.ZERO, Fr.ZERO); - } - - toFriendlyJSON() { - return `Leaf=${this.leafSlot.toFriendlyJSON()}: ${this.value.toFriendlyJSON()}`; + return new PublicDataRead(Fr.ZERO, Fr.ZERO, 0); } equals(other: PublicDataRead) { - return this.leafSlot.equals(other.leafSlot) && this.value.equals(other.value); + return this.leafSlot.equals(other.leafSlot) && this.value.equals(other.value) && this.counter == other.counter; } } diff --git a/yarn-project/circuits.js/src/structs/public_data_read_request_hints.ts b/yarn-project/circuits.js/src/structs/public_data_read_request_hints.ts deleted file mode 100644 index 4d2cc36b1fd..00000000000 --- a/yarn-project/circuits.js/src/structs/public_data_read_request_hints.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { makeTuple } from '@aztec/foundation/array'; -import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; - -import { MAX_PUBLIC_DATA_READS_PER_TX } from '../constants.gen.js'; -import { PendingReadHint, ReadRequestState, ReadRequestStatus } from './read_request_hints/index.js'; - -export class LeafDataReadHint { - constructor(public readRequestIndex: number, public dataHintIndex: number) {} - - static nada(readRequestLen: number) { - return new LeafDataReadHint(readRequestLen, 0); - } - - static fromBuffer(buffer: Buffer | BufferReader) { - const reader = BufferReader.asReader(buffer); - return new LeafDataReadHint(reader.readNumber(), reader.readNumber()); - } - - toBuffer() { - return serializeToBuffer(this.readRequestIndex, this.dataHintIndex); - } -} - -export class PublicDataReadRequestHints { - constructor( - public readRequestStatuses: Tuple, - public pendingReadHints: Tuple, - public leafDataReadHints: Tuple, - ) {} - - static fromBuffer(buffer: Buffer | BufferReader) { - const reader = BufferReader.asReader(buffer); - return new PublicDataReadRequestHints( - reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, ReadRequestStatus), - reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, PendingReadHint), - reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, LeafDataReadHint), - ); - } - - toBuffer() { - return serializeToBuffer(this.readRequestStatuses, this.pendingReadHints, this.leafDataReadHints); - } -} - -export class PublicDataReadRequestHintsBuilder { - private hints: PublicDataReadRequestHints; - private numPendingReadHints = 0; - private numLeafDataReadHints = 0; - - constructor() { - this.hints = new PublicDataReadRequestHints( - makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, ReadRequestStatus.nada), - makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, () => PendingReadHint.nada(MAX_PUBLIC_DATA_READS_PER_TX)), - makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, () => LeafDataReadHint.nada(MAX_PUBLIC_DATA_READS_PER_TX)), - ); - } - - static empty() { - return new PublicDataReadRequestHintsBuilder().toHints(); - } - - addPendingReadRequest(readRequestIndex: number, publicDataWriteIndex: number) { - this.hints.readRequestStatuses[readRequestIndex] = new ReadRequestStatus( - ReadRequestState.PENDING, - this.numPendingReadHints, - ); - this.hints.pendingReadHints[this.numPendingReadHints] = new PendingReadHint(readRequestIndex, publicDataWriteIndex); - this.numPendingReadHints++; - } - - addLeafDataReadRequest(readRequestIndex: number, leafDataDataHintIndex: number) { - this.hints.readRequestStatuses[readRequestIndex] = new ReadRequestStatus( - ReadRequestState.SETTLED, - this.numLeafDataReadHints, - ); - this.hints.leafDataReadHints[this.numLeafDataReadHints] = new LeafDataReadHint( - readRequestIndex, - leafDataDataHintIndex, - ); - this.numLeafDataReadHints++; - } - - toHints() { - return this.hints; - } -} diff --git a/yarn-project/circuits.js/src/structs/public_validation_requests.ts b/yarn-project/circuits.js/src/structs/public_validation_requests.ts index 17e988c2f74..b9e7d179b5a 100644 --- a/yarn-project/circuits.js/src/structs/public_validation_requests.ts +++ b/yarn-project/circuits.js/src/structs/public_validation_requests.ts @@ -12,7 +12,7 @@ import { MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, } from '../constants.gen.js'; -import { PublicDataRead } from './public_data_read_request.js'; +import { PublicDataRead } from './public_data_read.js'; import { ScopedReadRequest } from './read_request.js'; import { RollupValidationRequests } from './rollup_validation_requests.js'; import { TreeLeafReadRequest } from './tree_leaf_read_request.js'; diff --git a/yarn-project/circuits.js/src/structs/verification_key.ts b/yarn-project/circuits.js/src/structs/verification_key.ts index d7f5f4706c7..9b927bc834d 100644 --- a/yarn-project/circuits.js/src/structs/verification_key.ts +++ b/yarn-project/circuits.js/src/structs/verification_key.ts @@ -1,7 +1,7 @@ import { makeTuple } from '@aztec/foundation/array'; import { times } from '@aztec/foundation/collection'; import { Fq, Fr } from '@aztec/foundation/fields'; -import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { strict as assert } from 'assert'; @@ -85,7 +85,7 @@ export const CIRCUIT_RECURSIVE_INDEX = 3; * Provides a 'fields' representation of a circuit's verification key */ export class VerificationKeyAsFields { - constructor(public key: Tuple, public hash: Fr) {} + constructor(public key: Fr[], public hash: Fr) {} public get numPublicInputs() { return Number(this.key[CIRCUIT_PUBLIC_INPUTS_INDEX]); @@ -104,10 +104,10 @@ export class VerificationKeyAsFields { * @returns The buffer. */ toBuffer() { - return serializeToBuffer(this.key, this.hash); + return serializeToBuffer(...this.toFields()); } toFields() { - return [...this.key, this.hash]; + return [this.key.length, ...this.key, this.hash]; } /** @@ -117,7 +117,7 @@ export class VerificationKeyAsFields { */ static fromBuffer(buffer: Buffer | BufferReader): VerificationKeyAsFields { const reader = BufferReader.asReader(buffer); - return new VerificationKeyAsFields(reader.readArray(VERIFICATION_KEY_LENGTH_IN_FIELDS, Fr), reader.readObject(Fr)); + return new VerificationKeyAsFields(reader.readVector(Fr), reader.readObject(Fr)); } /** diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 192869a48cb..90dbbec53de 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -108,7 +108,6 @@ import { PublicCircuitPublicInputs, PublicDataHint, PublicDataRead, - PublicDataReadRequestHintsBuilder, PublicDataTreeLeaf, PublicDataTreeLeafPreimage, PublicDataUpdateRequest, @@ -148,6 +147,7 @@ import { GasSettings } from '../structs/gas_settings.js'; import { GlobalVariables } from '../structs/global_variables.js'; import { Header } from '../structs/header.js'; import { + PublicDataLeafHint, PublicValidationRequests, ScopedL2ToL1Message, ScopedNoteHash, @@ -295,7 +295,7 @@ export function makeEmptyPublicDataUpdateRequest(): PublicDataUpdateRequest { * @returns A public data read. */ export function makePublicDataRead(seed = 1): PublicDataRead { - return new PublicDataRead(fr(seed), fr(seed + 1)); + return new PublicDataRead(fr(seed), fr(seed + 1), 0); } /** @@ -303,7 +303,7 @@ export function makePublicDataRead(seed = 1): PublicDataRead { * @returns An empty public data read. */ export function makeEmptyPublicDataRead(): PublicDataRead { - return new PublicDataRead(fr(0), fr(0)); + return new PublicDataRead(fr(0), fr(0), 0); } /** @@ -721,8 +721,7 @@ export function makePublicKernelTailCircuitPrivateInputs(seed = 1): PublicKernel s => makeTreeLeafReadRequestHint(s, L1_TO_L2_MSG_TREE_HEIGHT), seed + 0x80, ), - makeTuple(MAX_PUBLIC_DATA_HINTS, PublicDataHint.empty, seed + 0x100), - PublicDataReadRequestHintsBuilder.empty(), + makeTuple(MAX_PUBLIC_DATA_HINTS, PublicDataLeafHint.empty), makePartialStateReference(seed + 0x200), ); } diff --git a/yarn-project/cli/README.md b/yarn-project/cli/README.md index cb164a202a4..76a90f506b2 100644 --- a/yarn-project/cli/README.md +++ b/yarn-project/cli/README.md @@ -7,7 +7,7 @@ The Aztec CLI `aztec-cli` is a command-line interface (CLI) tool for interacting 1. In your terminal, download the sandbox by running ``` -bash -i <(curl -s install.aztec.network) +bash -i <(curl -s https://install.aztec.network) ``` 2. Verify the installation: After the installation is complete, run the following command to verify that `aztec-cli` is installed correctly: diff --git a/yarn-project/cli/src/cmds/devnet/bootstrap_network.ts b/yarn-project/cli/src/cmds/devnet/bootstrap_network.ts index fe37e56979a..5d5ef4eff6b 100644 --- a/yarn-project/cli/src/cmds/devnet/bootstrap_network.ts +++ b/yarn-project/cli/src/cmds/devnet/bootstrap_network.ts @@ -13,7 +13,7 @@ import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; import { getContract } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; -// import { FeeJuicePortalManager } from '../../utils/portal_manager.js'; +import { FeeJuicePortalManager } from '../../utils/portal_manager.js'; type ContractDeploymentInfo = { address: AztecAddress; @@ -53,7 +53,7 @@ export async function bootstrapNetwork( const counter = await deployCounter(wallet); // NOTE: Disabling for now in order to get devnet running - // await fundFPC(counter.address, wallet, l1Clients, fpc.address, debugLog); + await fundFPC(counter.address, wallet, l1Clients, fpc.address, debugLog); if (json) { log( @@ -227,47 +227,47 @@ async function deployCounter(wallet: Wallet): Promise { } // NOTE: Disabling for now in order to get devnet running -// async function fundFPC( -// counterAddress: AztecAddress, -// wallet: Wallet, -// l1Clients: L1Clients, -// fpcAddress: AztecAddress, -// debugLog: DebugLogger, -// ) { -// // eslint-disable-next-line @typescript-eslint/ban-ts-comment -// // @ts-ignore - Importing noir-contracts.js even in devDeps results in a circular dependency error. Need to ignore because this line doesn't cause an error in a dev environment -// const { FeeJuiceContract, CounterContract } = await import('@aztec/noir-contracts.js'); -// const { -// protocolContractAddresses: { feeJuice }, -// } = await wallet.getPXEInfo(); - -// const feeJuiceContract = await FeeJuiceContract.at(feeJuice, wallet); - -// const feeJuicePortal = await FeeJuicePortalManager.new( -// wallet, -// l1Clients.publicClient, -// l1Clients.walletClient, -// debugLog, -// ); - -// const amount = 10n ** 21n; -// const { claimAmount, claimSecret } = await feeJuicePortal.bridgeTokensPublic(fpcAddress, amount, true); - -// const counter = await CounterContract.at(counterAddress, wallet); - -// // TODO (alexg) remove this once sequencer builds blocks continuously -// // advance the chain -// await counter.methods -// .increment(wallet.getAddress(), wallet.getAddress()) -// .send() -// .wait({ proven: true, provenTimeout: 600 }); -// await counter.methods -// .increment(wallet.getAddress(), wallet.getAddress()) -// .send() -// .wait({ proven: true, provenTimeout: 600 }); - -// await feeJuiceContract.methods -// .claim(fpcAddress, claimAmount, claimSecret) -// .send() -// .wait({ proven: true, provenTimeout: 600 }); -// } +async function fundFPC( + counterAddress: AztecAddress, + wallet: Wallet, + l1Clients: L1Clients, + fpcAddress: AztecAddress, + debugLog: DebugLogger, +) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore - Importing noir-contracts.js even in devDeps results in a circular dependency error. Need to ignore because this line doesn't cause an error in a dev environment + const { FeeJuiceContract, CounterContract } = await import('@aztec/noir-contracts.js'); + const { + protocolContractAddresses: { feeJuice }, + } = await wallet.getPXEInfo(); + + const feeJuiceContract = await FeeJuiceContract.at(feeJuice, wallet); + + const feeJuicePortal = await FeeJuicePortalManager.new( + wallet, + l1Clients.publicClient, + l1Clients.walletClient, + debugLog, + ); + + const amount = 10n ** 21n; + const { claimAmount, claimSecret } = await feeJuicePortal.bridgeTokensPublic(fpcAddress, amount, true); + + const counter = await CounterContract.at(counterAddress, wallet); + + // TODO (alexg) remove this once sequencer builds blocks continuously + // advance the chain + await counter.methods + .increment(wallet.getAddress(), wallet.getAddress()) + .send() + .wait({ proven: true, provenTimeout: 600 }); + await counter.methods + .increment(wallet.getAddress(), wallet.getAddress()) + .send() + .wait({ proven: true, provenTimeout: 600 }); + + await feeJuiceContract.methods + .claim(fpcAddress, claimAmount, claimSecret) + .send() + .wait({ proven: true, provenTimeout: 600 }); +} diff --git a/yarn-project/end-to-end/scripts/create_k8s_dashboard.sh b/yarn-project/end-to-end/scripts/create_k8s_dashboard.sh old mode 100644 new mode 100755 diff --git a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts index 1932986a768..c9d07ea4ec6 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts @@ -21,7 +21,8 @@ import { const BLOCK_SIZE = BENCHMARK_HISTORY_BLOCK_SIZE; const CHAIN_LENGTHS = BENCHMARK_HISTORY_CHAIN_LENGTHS; const MAX_CHAIN_LENGTH = CHAIN_LENGTHS[CHAIN_LENGTHS.length - 1]; -const SETUP_BLOCK_COUNT = 4; // deploy protocol contracts + deploy account + deploy contract + +let setupBlockCount: number; describe('benchmarks/process_history', () => { let context: EndToEndContext; @@ -30,6 +31,7 @@ describe('benchmarks/process_history', () => { beforeEach(async () => { ({ context, contract, sequencer } = await benchmarkSetup({ maxTxsPerBlock: BLOCK_SIZE })); + setupBlockCount = await context.aztecNode.getBlockNumber(); }); it( @@ -59,7 +61,7 @@ describe('benchmarks/process_history', () => { }); const blockNumber = await node.getBlockNumber(); - expect(blockNumber).toEqual(chainLength + SETUP_BLOCK_COUNT); + expect(blockNumber).toEqual(chainLength + setupBlockCount); context.logger.info(`Node synced chain up to block ${chainLength}`, { eventName: 'node-synced-chain-history', @@ -74,7 +76,7 @@ describe('benchmarks/process_history', () => { // Create a new pxe and measure how much time it takes it to sync with failed and successful decryption // Skip the first two blocks used for setup (create account contract and deploy benchmarking contract) context.logger.info(`Starting new pxe`); - const pxe = await waitNewPXESynced(node, contract, INITIAL_L2_BLOCK_NUM + SETUP_BLOCK_COUNT); + const pxe = await waitNewPXESynced(node, contract, INITIAL_L2_BLOCK_NUM + setupBlockCount); // Register the owner account and wait until it's synced so we measure how much time it took context.logger.info(`Registering owner account on new pxe`); diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index cd097c23658..bc59c817ebc 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -432,6 +432,7 @@ describe('L1Publisher integration', () => { `0x${block.header.toBuffer().toString('hex')}`, `0x${block.archive.root.toBuffer().toString('hex')}`, `0x${block.header.hash().toBuffer().toString('hex')}`, + [], `0x${block.body.toBuffer().toString('hex')}`, ], }); @@ -534,6 +535,7 @@ describe('L1Publisher integration', () => { `0x${block.header.toBuffer().toString('hex')}`, `0x${block.archive.root.toBuffer().toString('hex')}`, `0x${block.header.hash().toBuffer().toString('hex')}`, + [], `0x${block.body.toBuffer().toString('hex')}`, ], }) @@ -544,6 +546,7 @@ describe('L1Publisher integration', () => { `0x${block.header.toBuffer().toString('hex')}`, `0x${block.archive.root.toBuffer().toString('hex')}`, `0x${block.header.hash().toBuffer().toString('hex')}`, + [], ], }); expect(ethTx.input).toEqual(expectedData); diff --git a/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts b/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts index f77e6069050..594272d005b 100644 --- a/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts @@ -1,10 +1,9 @@ import { L2Block, deployL1Contract, fileURLToPath } from '@aztec/aztec.js'; import { BBCircuitVerifier } from '@aztec/bb-prover'; -import { AGGREGATION_OBJECT_LENGTH, Fr, HEADER_LENGTH, Proof } from '@aztec/circuits.js'; +import { Fr, Proof } from '@aztec/circuits.js'; import { type L1ContractAddresses } from '@aztec/ethereum'; import { type Logger } from '@aztec/foundation/log'; -import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { AvailabilityOracleAbi, RollupAbi } from '@aztec/l1-artifacts'; +import { BufferReader } from '@aztec/foundation/serialize'; import { type Anvil } from '@viem/anvil'; import { readFile } from 'fs/promises'; @@ -34,6 +33,7 @@ import { getLogger, setupL1Contracts, startAnvil } from '../fixtures/utils.js'; describe('proof_verification', () => { let proof: Proof; let proverId: Fr; + let vkTreeRoot: Fr; let block: L2Block; let aggregationObject: Fr[]; let anvil: Anvil | undefined; @@ -53,12 +53,14 @@ describe('proof_verification', () => { if (!rpcUrl) { ({ anvil, rpcUrl } = await startAnvil()); } + logger.info('Anvil started'); ({ l1ContractAddresses, publicClient, walletClient } = await setupL1Contracts( rpcUrl, mnemonicToAccount(MNEMONIC), logger, )); + logger.info('l1 contracts done'); const bb = await getBBConfig(logger); const acvm = await getACVMConfig(logger); @@ -70,12 +72,16 @@ describe('proof_verification', () => { bbTeardown = bb!.cleanup; acvmTeardown = acvm!.cleanup; + logger.info('bb, acvm done'); + + const content = await circuitVerifier.generateSolidityContract('BlockRootRollupArtifact', 'UltraHonkVerifier.sol'); + logger.info('generated contract'); const input = { language: 'Solidity', sources: { 'UltraHonkVerifier.sol': { - content: await circuitVerifier.generateSolidityContract('BlockRootRollupArtifact', 'UltraHonkVerifier.sol'), + content, }, }, settings: { @@ -94,6 +100,7 @@ describe('proof_verification', () => { }; const output = JSON.parse(solc.compile(JSON.stringify(input))); + logger.info('compiled contract'); const abi = output.contracts['UltraHonkVerifier.sol']['HonkVerifier'].abi; const bytecode: string = output.contracts['UltraHonkVerifier.sol']['HonkVerifier'].evm.bytecode.object; @@ -104,6 +111,7 @@ describe('proof_verification', () => { client: publicClient, abi, }) as any; + logger.info('deployed verifier'); }); afterAll(async () => { @@ -121,10 +129,9 @@ describe('proof_verification', () => { ); block = L2Block.fromString(blockResult.block); - // TODO(#6624): Note that with honk proofs the below writes incorrect test data to file. - // The serialisation does not account for the prepended fields (circuit size, PI size, PI offset) in new Honk proofs, so the written data is shifted. proof = Proof.fromString(blockResult.proof); - proverId = Fr.ZERO; + proverId = Fr.fromString(blockResult.proverId); + vkTreeRoot = Fr.fromString(blockResult.vkTreeRoot); aggregationObject = blockResult.aggregationObject.map((x: string) => Fr.fromString(x)); }); @@ -133,68 +140,61 @@ describe('proof_verification', () => { await expect(circuitVerifier.verifyProofForCircuit('BlockRootRollupArtifact', proof)).resolves.toBeUndefined(); }); }); - // TODO(#6624) & TODO(#7346): The below PIs do not correspond to BlockRoot/Root circuits. - // They will need to be updated to whichever circuit we are using when switching on this test. + describe('HonkVerifier', () => { it('verifies full proof', async () => { - const reader = BufferReader.asReader(proof.buffer); - // +2 fields for archive - const archive = reader.readArray(2, Fr); - const header = reader.readArray(HEADER_LENGTH, Fr); - const aggObject = reader.readArray(AGGREGATION_OBJECT_LENGTH, Fr); - - const publicInputs = [...archive, ...header, ...aggObject].map(x => x.toString()); - - const proofStr = `0x${proof.buffer - .subarray((HEADER_LENGTH + 2 + AGGREGATION_OBJECT_LENGTH) * Fr.SIZE_IN_BYTES) - .toString('hex')}` as const; + // skip proof size which is an uint32 + const reader = BufferReader.asReader(proof.buffer.subarray(4)); + const [circuitSize, numPublicInputs, publicInputsOffset] = reader.readArray(3, Fr); + const publicInputs = reader.readArray(numPublicInputs.toNumber(), Fr).map(x => x.toString()); + + const proofStr = `0x${Buffer.concat([ + circuitSize.toBuffer(), + numPublicInputs.toBuffer(), + publicInputsOffset.toBuffer(), + reader.readToEnd(), + ]).toString('hex')}` as const; await expect(verifierContract.read.verify([proofStr, publicInputs])).resolves.toBeTruthy(); }); it('verifies proof taking public inputs from block', async () => { - const proofStr = `0x${proof.withoutPublicInputs().toString('hex')}`; - const publicInputs = [...block.archive.toFields(), ...block.header.toFields(), ...aggregationObject].map(x => - x.toString(), - ); + const reader = BufferReader.asReader(proof.buffer.subarray(4)); + const [circuitSize, numPublicInputs, publicInputsOffset] = reader.readArray(3, Fr); + const publicInputsFromProof = reader.readArray(numPublicInputs.toNumber(), Fr).map(x => x.toString()); + + const proofStr = `0x${Buffer.concat([ + circuitSize.toBuffer(), + numPublicInputs.toBuffer(), + publicInputsOffset.toBuffer(), + reader.readToEnd(), + ]).toString('hex')}` as const; + + const publicInputs = [ + block.header.lastArchive.root, + block.header.globalVariables.blockNumber, + block.archive.root, + new Fr(block.archive.nextAvailableLeafIndex), + Fr.ZERO, // prev block hash + block.hash(), + ...block.header.globalVariables.toFields(), // start global vars + ...block.header.globalVariables.toFields(), // end global vars + new Fr(block.header.contentCommitment.outHash), + block.header.globalVariables.coinbase.toField(), // the fee taker's address + block.header.totalFees, // how much they got + ...Array(62).fill(Fr.ZERO), // 31 other (fee takers, fee) pairs + vkTreeRoot, + proverId, // 0x51 + ...aggregationObject, + ].map((x: Fr) => x.toString()); + + expect(publicInputs.length).toEqual(publicInputsFromProof.length); + expect(publicInputs.slice(0, 27)).toEqual(publicInputsFromProof.slice(0, 27)); + expect(publicInputs.slice(27, 89)).toEqual(publicInputsFromProof.slice(27, 89)); + expect(publicInputs.slice(89, 91)).toEqual(publicInputsFromProof.slice(89, 91)); + expect(publicInputs.slice(91)).toEqual(publicInputsFromProof.slice(91)); await expect(verifierContract.read.verify([proofStr, publicInputs])).resolves.toBeTruthy(); }); }); - - describe('Rollup', () => { - let availabilityContract: GetContractReturnType; - let rollupContract: GetContractReturnType; - - beforeAll(async () => { - rollupContract = getContract({ - address: l1ContractAddresses.rollupAddress.toString(), - abi: RollupAbi, - client: walletClient, - }); - - availabilityContract = getContract({ - address: l1ContractAddresses.availabilityOracleAddress.toString(), - abi: AvailabilityOracleAbi, - client: walletClient, - }); - - await rollupContract.write.setVerifier([verifierContract.address]); - logger.info('Rollup only accepts valid proofs now'); - await availabilityContract.write.publish([`0x${block.body.toBuffer().toString('hex')}`]); - }); - // TODO(#6624) & TODO(#7346): Rollup.submitProof has changed to submitBlockRootProof/submitRootProof - // The inputs below may change depending on which submit fn we are using when we reinstate this test. - it('verifies proof', async () => { - const args = [ - `0x${block.header.toBuffer().toString('hex')}`, - `0x${block.archive.root.toBuffer().toString('hex')}`, - `0x${proverId.toBuffer().toString('hex')}`, - `0x${serializeToBuffer(aggregationObject).toString('hex')}`, - `0x${proof.withoutPublicInputs().toString('hex')}`, - ] as const; - - await expect(rollupContract.write.submitBlockRootProof(args)).resolves.toBeDefined(); - }); - }); }); diff --git a/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts b/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts index e53fb312ec5..48d87598c82 100644 --- a/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts +++ b/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts @@ -348,7 +348,7 @@ export class FullProverTest { const { walletClient, publicClient, l1ContractAddresses } = this.context.deployL1ContractsValues; const contract = await this.circuitProofVerifier.generateSolidityContract( - 'RootRollupArtifact', + 'BlockRootRollupArtifact', 'UltraHonkVerifier.sol', ); diff --git a/yarn-project/end-to-end/src/e2e_prover/full.test.ts b/yarn-project/end-to-end/src/e2e_prover/full.test.ts index f5881b11a1d..0430ef690aa 100644 --- a/yarn-project/end-to-end/src/e2e_prover/full.test.ts +++ b/yarn-project/end-to-end/src/e2e_prover/full.test.ts @@ -1,4 +1,3 @@ -import { type Fr } from '@aztec/aztec.js'; import { getTestData, isGenerateTestDataEnabled, writeTestData } from '@aztec/foundation/testing'; import { FullProverTest } from './e2e_prover_test.js'; @@ -18,7 +17,7 @@ describe('full_prover', () => { await t.applyBaseSnapshots(); await t.applyMintSnapshot(); await t.setup(); - // await t.deployVerifier(); + await t.deployVerifier(); ({ provenAssets, accounts, tokenSim, logger } = t); }); @@ -79,16 +78,7 @@ describe('full_prover', () => { // fail the test. User asked for fixtures but we don't have any throw new Error('No block result found in test data'); } - // TODO(#6624): Note that with honk proofs the below writes incorrect test data to file. - // The serialisation does not account for the prepended fields (circuit size, PI size, PI offset) in new Honk proofs, so the written data is shifted. - writeTestData( - 'yarn-project/end-to-end/src/fixtures/dumps/block_result.json', - JSON.stringify({ - block: blockResult.block.toString(), - proof: blockResult.proof.toString(), - aggregationObject: blockResult.aggregationObject.map((x: Fr) => x.toString()), - }), - ); + writeTestData('yarn-project/end-to-end/src/fixtures/dumps/block_result.json', JSON.stringify(blockResult)); } }, TIMEOUT, diff --git a/yarn-project/end-to-end/src/fixtures/dumps/block_result.json b/yarn-project/end-to-end/src/fixtures/dumps/block_result.json index 266cf49864e..571794253af 100644 --- a/yarn-project/end-to-end/src/fixtures/dumps/block_result.json +++ b/yarn-project/end-to-end/src/fixtures/dumps/block_result.json @@ -1,22 +1 @@ -{ - "block": "1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200747f2ee8836d7dd230b97572463dac0576259dedd98d86c56e2275d6d670d30007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c32818d15e97da7dd64b32439cc63b7d03601ccadce81009ab9792a2f487795d30000000100b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000008019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a90000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001dfe666201fc6aee3c5fdcd21deedfa71790c6c7719d2af6919c068ef9b9f4c30000000200000000", - "proof": "00003e84000001f40000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000006b00000000000000000000000000000000000000000000000000000000000000011200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000000000000000000000000000000000000000000000000000000000000011dfe666201fc6aee3c5fdcd21deedfa71790c6c7719d2af6919c068ef9b9f4c3000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002ff40e125f72283eb833736e42285701b003d9e4270756ad3c5ba36ee0dbae760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e54491432d6c962973b71fcfd7b5597486f108bc66cd620099a65702fa0181b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f3dac4a356c5fdd79000000000000000000000000000000000000000000000001f8b97ff8c78f3f9f00000000000000000000000000000000000000000000000cf72074e065bc22b30000000000000000000000000000000000000000000000000002dc10ffccda590000000000000000000000000000000000000000000000047bfb4dfb23cc889f00000000000000000000000000000000000000000000000871e52274633f4bf70000000000000000000000000000000000000000000000013c49830a0ce95ff20000000000000000000000000000000000000000000000000002c5ab7c0bb98e00000000000000000000000000000000000000000000000b0f322f57a86900ed000000000000000000000000000000000000000000000002e496ababf56e3cd6000000000000000000000000000000000000000000000005dd1141d5deb2050e000000000000000000000000000000000000000000000000000268dc87f9458f000000000000000000000000000000000000000000000003334a597cd9ec0a0e00000000000000000000000000000000000000000000000645a57625996ab518000000000000000000000000000000000000000000000006a2f7ffb16256c45b00000000000000000000000000000000000000000000000000027ca8c331291b000000000000000000000000000000f4ee11b0bde295507e62592c4338bc1f290000000000000000000000000000000000268abf37ebdc51e432b543b9cd13eb00000000000000000000000000000080fb57196db1edb119c4a43096ca53be4700000000000000000000000000000000000c10cb089cb171173b34c8ab3b952c00000000000000000000000000000064a8f95c06b2f690c389f6e9ffbac2f03d0000000000000000000000000000000000305b974421c33e120c6c35e2d49d7e0000000000000000000000000000006360b1b9dbd90a9b1ccb3cd3bc78cd9ecb00000000000000000000000000000000000cafe05c1184abbb1673bebfbdfd08000000000000000000000000000000e9a8914e09dba59c9d0469eac4258a756000000000000000000000000000000000000aab18264ff95058a2bd32aa92ef6f000000000000000000000000000000430eafce70b21dd200f81e952ae95ccea2000000000000000000000000000000000027f21d866b6071e7d5888a222b23f200000000000000000000000000000035e18690ea3538d27c3eb3e49ff771858a0000000000000000000000000000000000253559923d3ef097c24944960baaca0000000000000000000000000000000409efa67b85eec9db156ab6a7caac5f9b00000000000000000000000000000000001379a24c97a4e3f27a72888913923c000000000000000000000000000000968bb1d5b9def16c7ba73eb743ab2082a7000000000000000000000000000000000007ca785c1c0cfd82fbce0d58a4dd19000000000000000000000000000000edd674059047c461b4014800a82e531a550000000000000000000000000000000000227a11996c17a4514c44e17b3e5b92000000000000000000000000000000eac24cd380dd1e269e973ef0e61f1ceacd000000000000000000000000000000000005e248521b8b312e944537ae68ecdb000000000000000000000000000000d2d1bc3109deba532ba528c5732d0a5f640000000000000000000000000000000000015dc7ad1bc5e912a04cb7fa12ff760000000000000000000000000000007c9ccd204792110580933efcdc4e4429b500000000000000000000000000000000000dc9d4003e306af0e5bdf9671ed3b9000000000000000000000000000000a33a9a871c7276da857c0bddcfe44bbf8300000000000000000000000000000000002cb33c7ca066c3c2dcfa000582713e0000000000000000000000000000000283503468afcb144e05a54e030a9a263600000000000000000000000000000000001c444beb50f664ebc2590d48488f1a0000000000000000000000000000004ba5bd89da5d04580ea93ca6e0569750920000000000000000000000000000000000219de77d73911f7d4b40973b92260d20c3f91a2efb28325f9e9c7865a0785c99e3e78307f91517889b623e5248c1920fa05558b23677f758b1a93e1be0e0008e5000c571c05b79bb4693559db73e6f1a5162de6db9f031e6c0d24bbfe35bc0b6efafece270978e59125b4973a997e31c579d28bd16855fb8e7019f0624f0ff8d201cc7331881b9022884717556a7a910df1d8d4f02a36374e38d9ec8cf380ca5c577925a79479d298593db4d0e676a153bcc1799ae8895ffaac643470b7d08e3ed2b39e276ed5620899c30b53ddb180b60f927b3c132347fb728509be0db26cc7461185a6514559b8fa1b648a8fc4a2a8d01adcc80c703889d7085ac6ec52b081316f493ccf91bd5ec3b00c9ca9a392e014410ce4234c9ee9dc4046a89608910a607f85241cb239b4cf7f243af905f1e611e72fbbe893a8994d50241f507c1eef1e806a456b39fc5e823c07bcf897c2f20f1a0e0804767b56b7e14dc82678c3f03b3dd3f22528e6fd5cc4964dd1cc72d5c0d02b0448eadc2f8582fad135db51484d2082a67671b12fc9c19d173fb4119f0b799734b7223bc2056fb84a7798250cb27fa8111bc7f9fc4bf1439ed0b031ec89ed76f1837d4ec12c4b2ea6043510f34d5256445911d477e444338f83d37152974ab6c2851a4925bc5821ced7e10b18aca14c98c1c01ed759d09310273bd0cdb0e8928bcae871efd91d81146bce75ffdafd5dc9b636d121237a15aefe4ff2558b4e99f5aa79a83c160f622073577c99dfd85bc90a921468b5def1b5e6a5813a21e2cdd0fba4d28ab9778b18e2e479db80dea0f335ba0c99f48c6133a1cdd07461930985f5865c1f0b366270971ec3f16e116402951a2cd461365ab808a7d2490cec89fd1b8a8f7553efd519e09529e4eb27a5d5a2398a3010473a191ab09277bc2fbf183afef00e98419a93d6c0169633acff37be4ab5f2183e22c0ec2f214e363cbb7bdda19d2953138d091b902e6e067f4b11e07213175ff514ddfd6662f48f9edca6f052323b8751a5243993f497c10a9d2aad798d875e0caee6e2d0f11ef53cfa924be4c88950b2f8945a4c1b1687a76b3bda7c5f7c0c9b55e71d6db1eb47d29d356167a16eea82725dd97766a0f507d88c6e2e46d4b05b23d538b16163d2eafec2e3803ae06a8936145dc5fc5a9d5f5f449a4da772bcd8393f3839c2297b279aab987372a939f6cc3a8a17893b88ced49e650a7435a0207c0b3d3dd1fe89bc2464bbacf010fcf500b666fac9fac31edd1dc466200b9349c75277a4b0a4c0696b9053d260df2dfdfd28e1171a992d0a44ac4a79ee28358e43d712e04202b8e2915cb56aa73518d40b1ca8dbb8ec3db522e6c7cecb6a1e3820b3ec7f3111e26921335ba8970b1c83cea1d5c2f9a01629825b9f082fbe2692c30da51320a275bb5e10a3ba1c39fceebc54ea1773e6df342be5e10b6b92934d943a3891510d8124b20c13df7fc3febaee595d47eeb7d91a06c6938e354e0242b7f800b7515c391766e31ec5cebfae28caadd4f62f8cdaf9715476ebcefea6047ee8d5c1a08be8ce510de1b1ef721232bdfb66b5aa8a2d3936a72f61866182106b6c04fb126da8402d04044fc34320ea7dc25529adad17903aed9b6ba818fd1545d5d9a8e261fca9c2dd9f4e46ada8b6dab7597b138f496b23ac9130b5e0809ff7a7f81022650da504f0cf0e569f01fcb54f987b4077df2ab9ec7475cc2ee32f61766a7a01c71a792b2bbb401fb5bcc06c53bf885ed51eccb40c1d3dcb77738b12bfc1c7c2f001cdc50e33714ae43eec90a111e3a95c6a2f3e562be4ab584223da1eda2c71064e6eafa71b5b83e51ec68e7a2702e0a4b150b9bbc4439b7dbc2edda5c443205eba641ee7ca513f36d73e89e168eae1253038be675a202bf49f8e0d01c3ee027c4c71190b85111a4a993acd70d5d59a41c3745517ee9454884aad102c3a7460294a40fb2aedb6d7e393491c86cf95592f8eb4e341a9383048ac54b95a98fb91d72578a1f41fe8df57999f4fd5803a1d804e7817e8a313216e7fbb20ef4bfae1c7abaf6230db02f7668ad099b6ac61eb58ddbb6ff081b11494d88e7d08e7b0e1d5151bd5f45ad09bd5d6bd55bc4877298f397c43756f385468b54490f6dc47510a7a4cb94179d0786421ff47903284154fd27b0c855f1afdcfaa89fd255b45008de625de179b91e5b38518c7edcc4ac3839c7c509af9e6612d48fbb6cfb50790d10dc8189a076946bc04e7c8eedd1d9c1c59c3f8cef6084560f127a6c887f4e18a35a3ab369418cfc8ac80d4d1d499be3ffec00c99b1228cebd5b22f3f9e65c2a77f0d8c3d31007f194cde62aac442a0a393cbbba694d7ae12f6d923f2f604426a885e6fa355c5175d4b07d75871c1d63cfd2d41e7fdd9fbf263b46c99bc1a6261200b5c29e0429f41890894a5fa3cb2434c68fabf6d6244b6f60ccb9545e3420fef06a696a636f93caefbcde2b199463402141bf92061a6d5ca1364bbbdbd6144ae133a44eac10081422a15b2566d5cd830da3a631056bc03e7f516bd15ce22c1186cbb384febe13f34df839737c0f1246573f0ccafd319e641e4c41853cb61cb2c6e5f5823a4680fe13e5e91146bb03eb22c7080aa5e1d14c4a7f615455b818e66c7bf833d780dc90aa5bf3c7e58f486c02986f1c551bcb6bbfd8a41f4971050e29cec4cf0ab4ece2b9214c7f2daed4b015cac222fca15feac05f41ebbb90230cd65386bd237067c3164b158e374784734b5d318403001f6836597dea514f2f966959a8b2cddfa0b6d5b3cd3193cb8961157ae0157943c4a8b0423f8c22a222742cc7ce54b1bc8eeb9e3d54396ceae8eeecb03f1cdc61585a4833743bbbf423861708b6672940f39c4d30689675e73238bdb0cd0b6f2eaab9d6daa5bb7cba1be67b411470e13b86af488cf6ef1f7a0748d52fdef40e51a45eb8358579e2001e6e499a9fcdbf253c4e14ae6c75c75c95097e8440edb9a794209d14bf9b096b01417c8a62766e3514850c040dcf1bd57198026b3a0230df831e90cf0a42d3fc29c51e9b0df6c9776190a624cec3c0a174a6dc72e6504d1e2084197ef41a90f71da03690381582c4805ff33db82a6dbc22b43468096b5a8b3135e5a3020f3c610af5c738bafeb2766c800c62db8d4c9e0439adc18f6837f5b1ab9a6f8f54325d0d89314b393a45cac216729563f8f491e637910021b1b6841df2630cf0664401123dcf9f67697dfe3f9dfc320ef75403c7366c86230df14bbc5949683b1f7e101332826dca63e48427b0b4d5d63a40ffb3aa5a218314e8b2192ef7463893ce99018e6f655bb29a298c74052d5cc0f98e6b7f600fa1d7cd3e2851a40e8fdd62b80efd4f22af41916d69c491126aff5b33f3bee2b5c3f7f036abfc5f584a6d39af279b2ba34a897c0732981fe04d212e62cae5cc4f5977b3e0b34068a555c0f4aa0856249aa4710a61d0f964c307828d20c33f9b63367cbbe45f6a3e43e1920505042f24355d1a5ae06abb18e1f57f1d83b5c5df10f3eaac777c9c32e79472cbb00de22b3ca4aa28fe8c8e7f445ad92b29198332bc5c83196bb52c8a28e12f92b9038610671c4f8070b088ec0c05cafc506bf658aa408df9f2d67e4654313a23c817771f0bf5fa4c65f3863106ca75926c6b6879542658d5d926f03031abf7614427b547e5c6871ae6ac39b1c7fb6c3a575a53696085a0e2483a7408012da3f4e122027ac76b7c469e3e99c3db7878fc0db08b107be62918ca5285e3d1ab7694700283c066c81606e966e4d491b0697d11602de7514cd41ef647c0731855ec8da5303bdd477bfb8f7072b0e1ed3355718bbe5d696f0e26969810aa60dde2091fff275394c7a0f9b50a8d9371e95181d164eff0da35ecaa736c5c6e74c9e5ef00e20fd2f16c7e0c0cb972a4cf6f31a38818c67f16b74bc20758d24ec212d02bde762d956c1a157c1dc40cd8c1ac7810cd1513a74daf430241f593036c6bb4a22f1f05f2a899e13342493d11092351fab93680ada41df6d9abc2c89dac9e52d9f169177992e868b700a1931eaa60239e9f3ecf4363f2f4e11c1573b101da9013de1f2c0b5306fe527c45cf4c570a8c0381f0d3ec37295f53a4d99e3cc17fe60fc6762181aca245535b2bff6172e615e9a6aaeb7b7ef072de6ac6bb16ee088d8717e7147ed8537f2102c55d9309f4ad82c0eb27434bebee4797bf573199107a9b6e1f0ba7a3d2f4f6f6a5d57b8f4bfb250eae52eadcb7dccf8034f35366da8d1d13a92f9e614c0f590afad82a14b4fbe124b66aa439d17fa90024fe93b58e43ef93ac0af67c378aa5af71700602f4f8b87eba98eff57c660a6122c7d2e40cd5efca992912c0d6b78d88de7920809aa66ba74f245b01504ce8cee4eeefa51faf7a4c4d2cb1f0efab958c0e007f3ea281ede0930b97daa5d3e6b85ec22e2e2384deefb60343bc64efc8b156f54ad97a6f6a1fa91057c332575e56c01913f39d285b71dc06aab65f896e2590e6806ce9332955e0edf6d485c2e51466e1742d17e437a63c2795504e7dd7056e6d9975d60a27fa496c008696486c2b2135a095afe70e725d17193efe90ae26943854b35cee9f9b656b8616c22a955e307439645e4ad2736b1baac9e704d35fd2c502ebe8a1297a525e8b50b0ed2225cec9648dee61e54ae01c43d9de2249cb108d9f30715e2f6d4c1a411e58cde060e538b413ec1505abe718df610004a08f7ec0157efd617086e271381a3413e73327037ba8531a8dbcae0a4b909e3c22453979cbbba7c9e8b338eb7963b6a2897559a35be81479e4265a26ea6198415b70fd4f12c48c72c90cc777dbaa8a0daaaeecd1705aa7f8de1e2e1fcbbbdd9c79310b7618299468be821f95c1de326161ce26439c05beb5a0d16909025e276e1de97d3643187c340acae1547e36162bed13320222a7690fcc95d31f05a6ced3f78a27bb4fc737d66ce18025f95b254e29b28ff371c33ea1bd8e132de3f054361005d06033267c285b3d9baaef4f929b1d1182fe0b5c18b50496d4143d760243baf23fdc07d7384e9ae5330dd37f71a87758d5412cf1a139da5c3e0929f3bf6cb32fbd157308fc5f2ba0b8af838e93c7e3e1fee780e8a91b5ba7161fee73232e207cf7f91c65a2ec78d494eab6bf0e3f477dc32b7c0b78c521106e02219a2c26e76d1a1c173ed0bbffc02063019c0741f268fbbfa4f160e7fec1c516300372af2e190ed7f4212af578ca73017382150fec38fe0b5c279e1fb5a30611751f2b2ceb7003e13c353335bdfd021037ac2e164f70b7369b831188a5d3301c9b81bade3b43ca3e32ab4d1e1c3df573fff48435c41afd9e182bcc1c725f4f2416b598d7f90c4d87d2d48e377235155a7f34f0ed9d5960273caefd4868bb600d4c13ea609f29f2b39969780d60cb4d737752b3d7828618d4204a1e1f252c5f2bae870edb31ce84bb1d1fc6be8ecab20a45c184c12d73ccd4d92b64e985f2bb0da0cb84306678bc0f2ec5861f17012024e0eeebe8ca9b71050e8e59ea270aea238716cb6ea62eff41f7b10ead872176959d6ecc6046e3e1bfe600ae368afaaa04261e59bcd2eced7fd1bcadc84ed2788a59e6189e356c5bf9d2872249671a9408616c8b96a79de09262c726bd0a85b2ab758fc30ac52c0807086ddebe44c5d324ddca837c33f01b7c4a190cb1f294f574d6a8a022a858aab49e23020162abaa2b3c74d5bfdf8e677205713ab3524400cab5a78d23d9d47a54d2cc13bee6d4d1002cadcb2c914ff3180d62619508ff811aca4904f4d5c7e34d8cd5427316622d0cfdba13fbb72359562838a0dfe1c07dc96d3f29a3cdcb978c100ac75337f7ed264a617d779ef92efaabf31f8d8ee083ef13951e13b7341a32ea5a206ba0e74807fbdcc9fb35a66425f2468df7e3462a97f90c21c6b6ccf03653dcc4a07a13e4188beb58d73fab9bde45f64462d5df158bc5486e5ffcb61267358818b0a1c531206a02999da5ae0e0cb13cdfcbe448e75e91a085756f91f11204d24b9ac26c9f05b0909517430ce3afc8c0959296f0a1a9b708f468a2503ace0ea90dbec7d2e61293679bc3ca66d5cc8133883cc39c89f1650472d2dbc0addeabac8be5736a0f2927c30423c73636944981a57bf36564e3c454f40a4aeaecbcde88a2045b0d7f22ae98c1431ebb5f8827f43f16e6dc1809df7d40b745507cf40db1ae36a1289c206d0b8015b7cf444af29f7e552aef13d8ee4d0dcbdd0b18b35247663e14548319587bce9e2f949b13c8ca7e7e6a7db53ab00b82e8a0144b89a128f7d513ca7407319f5b0c2ab6cc53d3cf9e27ccdb7e98439506d9873e62c87989d7c525e5c62e1ebecaaef0968a8348a1afcaddeaa543ab271f868f4ff41ee72a782270dcb6095466996accc8f37d6b5054c8f0d3cd25af16c86cec489e5a97a2687f9f13d72f8ab24af842626811592ac14f00f47ae1d66e720e43050bea628a6b99a5e20b19e249b107819b5d02e4ac952fc11d716b971227bbf3bcdcddee7272a5c17d1517f3ef792dfed212cce5b4d30ae9d7bacf4432673c597e94a1011e6280c3fea201a709a353d1d7806ef92d17360bab66478ff180f0dfa3452b705a770e9c56b411bd16547623412a971554709dc5adb66ff0dc0913c1f173bd27f9f4807e72232edc4abf1c224085c921e5cec13064839780ef3e80ef272fed1e63a49b289fa30882621de391a717467195fcf23c2e7c7b043e6ee69d66b1c420f3416c33dedb251819bdcbef3b69a2f1a1dd4e6f9b638efb8b2a958de59ada940fe569919ce30b9138168402ea07cc57bc407820d261747f65c3a60c5d3c72e8dfb37eeb164429a574406a0e051276136f142695deed52557dc804ae74074585605e8cdfdc321cc161214c24b8930607b959c3b873f8887136b7a533609b0cd6e323637df3e719e28cd4075be0a5fe6afbbcb45103ea744a9b117fc79ff7c8e4ed2eb0f6ae5c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000755abab3f7b103f419606830d0d840388082435895411b90d4d8924e338d288225d20cb965acd1e966f30241e086c65dfb43f7a3b3e4a6264efe306397505692f3cae8e2b6e6c66d0ca6d9b1085f3529b78bd6b665110ca038427e6e9d5deaa1bbe84a25e455e3c83c39ca18892a482e47b82b7a89e9b5be7529a62dda6f91d0c7828de87520f74267502a1124d4128b9bf6937bdc4843714ec57484ae3faba0ec3703279721edd0682063125f10f22f57f1436b8c837bfad0d09501afb8b1401cc20f14c3fb3adfb07fd941b424725f3961a029488cf77733e63f3a521d47c2b4566e34ecccc6104ee261c33ead96a55f0ae11e1101dcba121d4c9e5eb2ab10034e2c91d4fe984aaefc2a6ca3613348a352b522ed427b004f5cf0d7bac0b481be7bba8fb303fc198a0a0d128592a6383d06df04cab44900c424b19d6e35bbd1d493542c799cd103e957f7396192d236a3c57bb662f3ae75bfc452022f6522f03c29c5a7aaeb266653eea78f42e09900e9e4938dc3a631de28eee2e9488a2762a77d7b4c7dee04743e2fcd5859820a14c81176e9cdc6309f3362ff1ed57777b0b52e5cf478b27a59deabfad2162bd98d9306dab3b22e59486089afc983ed8862b9a7d10611b8f64f05a7ee0de0b47d4bff6f7e19e7f3cbff886461fec1141552263408d7b25e069229b0f58c7300a2f9737c94a9393736c8c11e4c11341890a1d5019f4fdb6e14253909bc1c68466f133fdc96c3bd64700156e6b4568f37ffd1f05340dc04a7ebe8ad4e96c0d0c240ee10abd9b57c5cefc1258a345c56855df0340e35b136571723ca5c477df6c6ce878b90aec1d72dbe229c5be0e3c6fdec5004286e2554287cc7093855ecd4edc7f28fc3de48e040fc4793716e35dbd7d9a26334f4bfa504942cabff7275317ec9dd5c117542ef13c8f0761bef5232a0f42062539b418b01be15071dd250ebface7f45f09cefaea981d594e1fb651131a9c00e29a561cc35341d9bcf8479f03bc621d77840199eec0cd6322278c7c010f6c0a0c3cbff7f1595854424eb82ca3ed94fce1e88d256cd64a071420fe16a6c05e257d6fc9fbbbcf49f89dd2e55579b233386ca18d09a8fc47f3b2b768e60c9d812a664203c1d1e818c9441fbe811ed45d87846a322cb75e41a93cf0dc9f04b8521bb3763468fc29c6203915e8dcb535206d4bef5889a66ad062a0afb84cbc6cac0195bda43c78ef436e0f701f203a2440604c82babfeb07632abfd03011e82011282d27f4bf2b82a075d7580f601099bfeead7156eec207b3126ef0e955f03dca17fa89336ca99efc58b8a64a0e377e369e56db279c031f27d758a6c3b407edc90f38ac48b13d1f63252ff228e3cc9545a9c7bc4b38123dcf50d3f41b148ba10023a1e58f26d71dab1261af500d59f5d189dd43cdaeb9dc266882d8625bf669f911694cb35ab7aa98c1d1b716d150a4eb113f034a4ce7da5a09196ad3ee4e46b40e8aaf0ba5f8fff8ff4d20121441aef29adfc75d4820f78c44198912a93b2072296d7a2582177afbea66ddb25922caa396fe47961c2877e82f774dcc0c3758930e990ee99a8bccb5a50dc90b6721a874091dc762214e56d5b805595475577b2b28d8582ee519ab7a55bbf31cccea5475eb0eba4b6249cb694e7887a65dca7b922675f4bb3e5dca94f1a93ee6efb7165bf4d680cc122dfc48951b1c213c072e7a2c154c2bf538ca9b03f05fa292796086dacaf21a080c3d809674930a04b23598120096e180bb341e3da46ba1d6e1972a59fab49ef16c1e41ebbb783c0e96e7ca1e978911febab8b024df68a2e29fee6fa9f48f7fcf30dcca3dd13874fd034d5711faaf385ef0ad1c8d23a2f36e7c6d3bd14114522f95544c6cd1f8da0257758a000000000000000000000000000000b2bb591300a297e0a753862627bf61b14800000000000000000000000000000000001154933493f3bfd5a9c11b142c3717000000000000000000000000000000a0aafc71c55c4b8483d9e7aef3086cfc570000000000000000000000000000000000039357f77a572f20464ef0be7f46160000000000000000000000000000009cc129b2954978cc792b1535abe0e678ba0000000000000000000000000000000000210ca7c06f146386f9911070d2c18a0000000000000000000000000000003ced3aa175bdabd5eb4b50e2b1876f096700000000000000000000000000000000000f60d5d5c2236f2f9b27e95561781e000000000000000000000000000000565b50a254b922477f8a1b2493656891a500000000000000000000000000000000001a9b39d2ea0535d2953aaea59a8720000000000000000000000000000000bd15bd55c77c56b6390273d0054bdf4e1e00000000000000000000000000000000001564812d349548f16e4a041ec9cfdf00000000000000000000000000000076773335bab1d7b3e8bb293b1bed7b714700000000000000000000000000000000001fba381793ac902ccd92c2739c6f5200000000000000000000000000000075a46556945910ca4724c38e2abf6a64c000000000000000000000000000000000002c0f17e99fe87402a07fc23224fb9400000000000000000000000000000088fd65468ed8af24dafb5a1760b46f463b00000000000000000000000000000000000090a3201e6bd5559a8c73753c2fe500000000000000000000000000000008a63096070df14d043b9fc73bd466baec000000000000000000000000000000000021f085a0da7846087d69d27449e7e5000000000000000000000000000000661c396474836dfa9270a44f3645f067a700000000000000000000000000000000000ec1483f6cb6321f8a96fcde4ee618000000000000000000000000000000b81c5866353d91337b0f0eabe62c0d700300000000000000000000000000000000000d379ca8660e86b61c308c6e16518e00000000000000000000000000000053656c0b8d26d5d7c4ffbc84cb8c8dc78000000000000000000000000000000000002aa9ba2af5ea1164b866e13b2c16d1000000000000000000000000000000922021c4c51e3061eb00b48915e506ba45000000000000000000000000000000000015eca982d68e4abe53d58d4bcf075c00000000000000000000000000000085c04ffd527c9209edf992b974cbeba83900000000000000000000000000000000002ba65d580a93a360025f56b8f592a6000000000000000000000000000000d0f88ff226a3ef57f1f592db98e1d827910000000000000000000000000000000000042735accfa3e630a25d172a09f3f2000000000000000000000000000000847902d41483ffca3c114c8cdb4cedd145000000000000000000000000000000000023efc8d31277e79f56e7613272eded0000000000000000000000000000007a7c50b57185b83ac18ba3261e220d7fe10000000000000000000000000000000000199b7e3b8e089834da02b8b41c1ba50000000000000000000000000000008acbaf87e441a6f1fa602118b02a8793cd00000000000000000000000000000000002ec63fed5f835087f8e1418d0dfc1600000000000000000000000000000020f9c0878fb3277d8d19485475c595827000000000000000000000000000000000000499e7cc31fa2a39831fdf7df8513c000000000000000000000000000000184428a24e481dfeb599723ba6c02288c00000000000000000000000000000000000187c9d4dedd2f97e8a8fc0fd129383000000000000000000000000000000fd6667fb403d52b2991a570668382a43f300000000000000000000000000000000002230ae1eb1441db0886e5443aa7aa90000000000000000000000000000004459f189b482e036feae0da6e37c7fd7590000000000000000000000000000000000182ca7fc790dff23214209ba3d6566000000000000000000000000000000b95f9880fb46bbd90b5117dadf9e67726100000000000000000000000000000000000f15d77545d650bc2a882ed442b8a2000000000000000000000000000000700923f7fd6c51e4941184ab0d23b2f1db00000000000000000000000000000000001e7521d6bad6991d37eb8cf06971320000000000000000000000000000009d81f92a7875c29bd986187c67b812da40000000000000000000000000000000000007c0de4f110d28addf1d83d7749cb0000000000000000000000000000000f38cd83b6ce267d4aa382e6f207591f62000000000000000000000000000000000002f8dbc0ef0e84723c125d13bd0d1e80000000000000000000000000000007d03360528bc17f1fb1181c979746ab2b200000000000000000000000000000000000bde2ae9c687c6f2e4495cb6ceab9700000000000000000000000000000004bfa8f689b7df8174df8c96f57872ceb400000000000000000000000000000000000177e08abb1a6fd4f220bcccb07e62000000000000000000000000000000d59961d99890eb911c402b007b9cbe976d000000000000000000000000000000000001e44c4d03753c3c68e2f72c29b0af000000000000000000000000000000e10bcda37f9b020238ce42cafba364ad0b00000000000000000000000000000000000a2700ee4bcd2ee1f9d187fb9a58ee00000000000000000000000000000034e61a08bc6a2102504fff403b37d354a0000000000000000000000000000000000019060a7026ab5315caf29609416bff000000000000000000000000000000a0b9296028acb200c6d9216bf1fd05587c00000000000000000000000000000000002537afeb211ab20661ccd797030db90000000000000000000000000000008d6fd1fa3c9a7902ae33325a7481e6ead70000000000000000000000000000000000105d1d3ad744922019ce40015b731b000000000000000000000000000000653ae5b8b4e3bf838c8dad5f00baab715200000000000000000000000000000000002ca54cf76b2d0eabd4dfd4c2f269b7000000000000000000000000000000ed0fa724e64d0bb3e921d29010b254b52200000000000000000000000000000000002283dd0b6919a9b907efa0d1450c83000000000000000000000000000000247d9ae0da38579e4d8f9edbafee4b0e870000000000000000000000000000000000038619b10948cee4ab41f87863ea55000000000000000000000000000000c86cf7a365af37b59374be4838604fda5400000000000000000000000000000000000949507e05840a340738aa0059fca80000000000000000000000000000005b9a32f04b291a93fced33191d11eee64700000000000000000000000000000000001dbceafb63478c33422a6f7b27b729000000000000000000000000000000949df4a91191d0883796d0c17e02de6cfd00000000000000000000000000000000001617ac2fdecf6a50088e4f9e89e09c000000000000000000000000000000d46babede40775278eb51c34e5354e155f0000000000000000000000000000000000214599b8fdbaafc8ef1b5eda1d1294000000000000000000000000000000770087323d677abefbba29108b9a928c3300000000000000000000000000000000000806db3099dfbcd0b4b60d575268960000000000000000000000000000008cfc1070fca86e46a864c883af230b0f3b00000000000000000000000000000000000bf85e10e77edbfff9bb9c84b76ee700000000000000000000000000000015d43e3775742ef07d4d253ac41af7234a00000000000000000000000000000000000bb11cc6d7c81d0284afccb0bb848c00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036a960d6f8e4ebd5c4e7619ef498b47415000000000000000000000000000000000003f8bc6c6f49222e71da7ef4f12f59000000000000000000000000000000da0e9ca5b0bc2a8b9f8dc55583a2f0607000000000000000000000000000000000002b34854ad662b37e0e76506e3eaf170000000000000000000000000000004eece60b91287df5941d8b6b85a1c163d4000000000000000000000000000000000025121f27276f7d6405b64dda2d13bb0000000000000000000000000000006b80ad59b5eaf076a2963328805fa2200f000000000000000000000000000000000018c545a23c08a38624afdc86a65d280000006b", - "aggregationObject": [ - "0x00000000000000000000000000000000000000000000000f3dac4a356c5fdd79", - "0x000000000000000000000000000000000000000000000001f8b97ff8c78f3f9f", - "0x00000000000000000000000000000000000000000000000cf72074e065bc22b3", - "0x0000000000000000000000000000000000000000000000000002dc10ffccda59", - "0x0000000000000000000000000000000000000000000000047bfb4dfb23cc889f", - "0x00000000000000000000000000000000000000000000000871e52274633f4bf7", - "0x0000000000000000000000000000000000000000000000013c49830a0ce95ff2", - "0x0000000000000000000000000000000000000000000000000002c5ab7c0bb98e", - "0x00000000000000000000000000000000000000000000000b0f322f57a86900ed", - "0x000000000000000000000000000000000000000000000002e496ababf56e3cd6", - "0x000000000000000000000000000000000000000000000005dd1141d5deb2050e", - "0x000000000000000000000000000000000000000000000000000268dc87f9458f", - "0x000000000000000000000000000000000000000000000003334a597cd9ec0a0e", - "0x00000000000000000000000000000000000000000000000645a57625996ab518", - "0x000000000000000000000000000000000000000000000006a2f7ffb16256c45b", - "0x00000000000000000000000000000000000000000000000000027ca8c331291b" - ] -} +{"proverId":"0x0000000000000000000000000000000000000000000000000000000000000051","vkTreeRoot":"0x0682f798cbd4d79c13a2f650654b14b1c1f90cf56ab0eb53f2303137316fd110","block":"168412281b25723f31c01d87dcbd5eb4bfa1c9d497054276811f7b1b60e8a9260000000a000000000000000000000000000000000000000000000000000000000000000200770f3c19522567719f7c16a16168cd7d360a58a085351d24e19981ced404bd00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000a01c4f87a8c97de8261d1c8917492b3f4c52a4f7d62783a50c8068bc54a9f095f2000005002164b077e0d3ae48b923af55339853f6077a68b50272d8414a9336b484a7fdf3000005803001c6ef98334f2cc43764ea7d811fa76f1ae4920f794737f04227ed57f35a9b000005800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000066db32e400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000017d9770e08ec6a88f0e5308085c1da0e4271d46ae7a9a42a52d7967aaae9da14ef5a24a10000000b0000000200000000000000000000000000000000000000000000000000000000000bed2f5e000107aa36912351af5e47e85b6bde747868b34cb09daccda474616d09075bbce1780002098021189e3f5a9a448d3283e621791b2a280964f8e7e57bddd10f8faf79154b00000000000000000000000000000000000000000000000000000000000013880d87e811041d9b7f4747717d508f7be2570a92a24dd1f7572e871bae1cff83d800000000000000000000000000000000000000000000000000000000000013880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000040000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000bec47b00207d0acbb35869b1b8d7df8f9c9ea217f9cad8f9a4b2ab2a655acfe9ff672019d0f8434eac2f39429fc5a560045e27c6e272a4fdce8fb4f891a2abd2cfa4f72d2022cf34eca3766f7f0c15ed93ea433946d790d54ef538a51635bbe7b9fa7d09cc90e94192696ac67a8c77aecd3540d3654bbbf79a4a52bbe350557052764c7068600000000000000000000000000000000000000000000000000000000000000000408000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000000000000040c00000408000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000088560f0f994ba3f5bbd628798917d2603cf3459a90d8b2e12918ee2364b712034c8a99cb64ca689e91887a76a4704ef83e800a49fba0d4b8c9f1db7bac462020b110f454eaccbb0080fe5e8c2ca5e8725a1a4126a8428707c21475b05c6c879669ffefa13c2e31ed4fb7ede224b5271c5616d72847e415d8782620edd49dca52c6920644ef4b77f85abe3d2af9bd5b3c3810a30d76090bec7ed9df0a815b0544aa227930a27ae9d052b02cce25d703b392a48101fedc789dd9e93406f944014858347901598744d5c8aaeaa8daddb794023ac23385c49bdab78bcb8b3a7c1068dd8a545be5829fa9ccf3c28ee45be5ddf76e1c446ec57d422676056b7ea388f2ee1003dc5f085642323ac9405fe528cda36331f6f5fb0da478f0f4c6b79a76584f0bd2a67ec965743ee2edfb9a8dad254354c72aab7cad1add5be6f9189a797d93ca2dc84be3d4dcea7a9a1df295e9b690387f99ecbbd46cd35f036795f60ecb2a6dfad512fb601828602e62b0d4aaf54019e0613eb2882582dff3903d609bea13742e186e1a574ca42caa496f05a6e7cedc8f1b706ac27b179e045ab1c87749806aa19d6e6c8ed0957098fa38c99da5019278e0f86bcd1f83e801e10debef5900000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001fb5cfc23d13c58bccbe4aba8f1b0649aad5f47c67aecac3d288dd72040d4b46cbce4fd84f3e184a7e0b995ccd758577cbf2e2516e369479063acfe2193aafc1c07cad0765fa4afa491214a84cdb36a65b21c0d0011cd24c5118b2e2132d4d6eae2923a211286d0d5106a9ef375139435ed7423910967724d33cb2c1455eabefc39395d3ca5482f4450672e1d7733e9737faa3755756eb92435ae5524bb4cc43a6f0751e92c8a78015099e97804fb3e09df278f828b4f2df39969e49dd42919fa9bc412ebe799302d7147ca7c3057f0e13d0dfbe8a0a799603cad60db29bbe587e0235dd3c271354b02103e9e3a3b0fec304fc07123331fe8efd4dee89c70a04707907e8a4737bc23ee7ea6aa737412f06adbbed64f3f88cab2b9f25e342bc37ccfd63ea6c2ea22fa0236863db4c659bafadb24041b51013403d813b9c923267629c4d21becd352980b84273d42320b8fe7b132c60e508832570fe23906ba61329934e265fbc4bf58a6a1c1b9e3d8816b6169acd318b3c5ee6083d2e41836dd5cd288d10367253af00a383368f798df4e5456986a756f2476c50309fd71741ca62d125903345799708ef0aef33099ef6e618282cb942e63bc0b5474e4ca651a20000022800000224000002200513f23dac12350cd76868b8a3d05065c3791a3789383d1fea9ac3ccc3be7c830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006fb08e47bf4a5bacd50e4a162b67d37ddc33cd3aa7216a9e8ff64e301e30df68a39e315731c6cf7ec6fc433a3b8c1a5f0ea486d6b693c1f4180b57476b9b2c0eb87ae8203a12a3a53798bdd781187f28888ad2c4d0cb583c9102610fdb527ad793c1bb58f0542b77d710c2eb23b5f41c5fa75139cf5cbed830552adfd309ba56e4704ffb7d2f1a181d88a4c29dc8413fc873a5c127e221f5f0925613f06fbe49af6b243238ed369489e0e5a6e23f81968ebc1b45159de50996370730538a24316bffe41cc183f5afbbd630f8a6c1bc1d56782546e63baf390a9a95a8a4f707412f2ca990db35154b0eeee962bb363de1448b249cff1258e0c3964e5b922ea23e967025a05b79cdb949cc14156b74e306b254d304ea54662171c68c622e36687f3f8b029a40fde2493e336aec8e03b1b883bb11b849a100a30a591f805fa2e2a65d9b6aea0a78fb16047c7aca474818d342aec0e71d695b7e20af06a78e5f4052f6173139f83a3f183995062c4a7e3212c9c48ed0581909f39b4fe3f4a834c9f3be24047a2226fe7b78e7974521c71d114c8b318e93e3573a1da616d90dbe3d9d73963df0e3355a197feb54545ddaf20e376bbb0ade6b0e7c693510d1da27b9a0000000400000000","proof":"00004244000002120000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000006b0000000000000000000000000000000000000000000000000000000000000001168412281b25723f31c01d87dcbd5eb4bfa1c9d497054276811f7b1b60e8a926000000000000000000000000000000000000000000000000000000000000000a08ec6a88f0e5308085c1da0e4271d46ae7a9a42a52d7967aaae9da14ef5a24a1000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000016e43c5ced27da8b6f2fc788451dc743bd619c3763dd038512e1e02e4c8c6f440000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000066db32e400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000066db32e4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017d9770e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000682f798cbd4d79c13a2f650654b14b1c1f90cf56ab0eb53f2303137316fd1100000000000000000000000000000000000000000000000000000000000000051000000000000000000000000000000000000000000000002e3059a3a513ebd2100000000000000000000000000000000000000000000000acb31b01e879a466900000000000000000000000000000000000000000000000e4156ce7e68f8d05b000000000000000000000000000000000000000000000000000207a06299fa9a00000000000000000000000000000000000000000000000165ad30b03ce3eb2d00000000000000000000000000000000000000000000000a3a7147ddb3b9458c0000000000000000000000000000000000000000000000016e5155e9178c65c8000000000000000000000000000000000000000000000000000068b23602e6fe00000000000000000000000000000000000000000000000f6efd39e580a3e6100000000000000000000000000000000000000000000000082e36b8da2b12bc49000000000000000000000000000000000000000000000008ed75e19a27997c5900000000000000000000000000000000000000000000000000017cef742b6868000000000000000000000000000000000000000000000000fd810553a9e73f3400000000000000000000000000000000000000000000000b145e0a2ee85822fc000000000000000000000000000000000000000000000003b13582511a99c9940000000000000000000000000000000000000000000000000002865bf9f95be9000000000000000000000000000000e890e23ea66995ac0cd157ad66203420ba00000000000000000000000000000000001c001ed135ba5936f3a916a97177a900000000000000000000000000000064678cfe06a8015932a3e281645a534c0200000000000000000000000000000000000675ccb0e38833042f9c8dabdfbbf300000000000000000000000000000007ee7d86d5d35b8497170aa93149d6ea9f000000000000000000000000000000000017a0ff465881fb66307b71208429c3000000000000000000000000000000fdde0ed9f5c731c7f476c7df130e7e4a200000000000000000000000000000000000017f5ddf57f45a9aa6288b3feb101800000000000000000000000000000027995bc3cd9f6ffb368b2d8524bd9b802b00000000000000000000000000000000001cec85cc344dcbf75dc4b68e640e34000000000000000000000000000000dceeaa901d6af7095576c5f01243416eb700000000000000000000000000000000001f0de24acb0d0392930bf4336c8ce8000000000000000000000000000000c3562d3de20254558799fe1cc6dcd83d47000000000000000000000000000000000012e94fb56eca2710e5ee89f76ca7bf000000000000000000000000000000c8e15d87aa3d60f470e3f45067e43f8ea900000000000000000000000000000000001d068a50ca319ecc7c91255068c4cd000000000000000000000000000000f10600b8565647170aba4864d7d764729600000000000000000000000000000000000890c5f08938a81e9f7749cb8d0fe5000000000000000000000000000000c5236a4737f4ba302ae6a186735d6703cd00000000000000000000000000000000001245132eeab701ce68da11c25e6f7400000000000000000000000000000058af1b0a892816a68b47f1d913396c02a4000000000000000000000000000000000007228bac9d853b2aaa5a424bd20eb8000000000000000000000000000000f18e69117cb80bf7fdea3aeeff5dab8d9900000000000000000000000000000000002c015dbb072d722403f4728fea05aa0000000000000000000000000000001156803aabf9b319bee320bbef73efaf6600000000000000000000000000000000000453bba56f5d72c28e338eae272c17000000000000000000000000000000c299833e9f322019bffb0bd9e75656a60300000000000000000000000000000000002330e2edafd8bbe9a0abb1cd860440000000000000000000000000000000372449d66cd4cc5db696dc322f7ee3012800000000000000000000000000000000001583bdb63325fbeb57bda9e2ff70f8000000000000000000000000000000be29e683f6ada33319ac9a523407fe264e00000000000000000000000000000000000de6b54f7f3d9d54d36e2961fa376c17b7f860176ee3972e7cc5bd5511f9c2abebff7e18143725b603eafba3a505f518ac5612c9c2bc9289d37ff92c6f5e9a7c47e8ca61a5396b8dde0a984c5afa0c20d87055e7d7872895512f79682588689bd04a7053bdf14c54973d913c2a8ad11c627a0c55d075e872109b2c525f2c904c860ad67e74228e47dc4e1082321b1117f1d69d1069d0c732313407ffa64e4d757689ec7df3b6d6e8dbada090f4f7e40ae8d5151e9b492b63f3c92f8f8276201887061c7b34bf1d8a4be1c6d1e8c2790c07331c29013c619653684d2d56af2b01f123f6bc659b5caf2e30d8f13c2d4628a582d3882a9af99e1216411f61ede2117ad47124bbfdf2a2c34cfe8a3ad55801431292fae6ae7152f2ccd6a1e97dd6a006c867c79ec9a88cebde40cea2837814d566cfbd8792b59aeb248ad90af535a01b91ea94039e4d73e246c68427fe320f89d71c640a23c60f5e98ac5951595bafd93b1cffb420994a5281456a5174602f6a07795c2b9df7994e0429c1830616218fc6c0a43a2013a934bf1ed6a83851294c4cf42781ba7ccbcd0c874e14ec3a73e76dacd2f4fa4c97ec61f681ff5fdd23c8c84c119e4e874e80e11b68a8e564ed6d5b3957023c8cfc3b085781fe59c617dc32cd82fe63fa9cdcaf5b711d9b5cb6584e97cbbac645c7b1964134c52e1e26bb7e9efeb4c2143181f3add3dc8113f124ed3bf393590824af3b1522dc3bf626db5481496d903b8101a71797aac69bdc8296591d77177ec38eb47d6a03ef5e006752754121fdcd97edaeda2fc4eaadc34598310fed1e51817b403bfcf8ace526079895e0b13bb1b39d335a3040e6bcd9647559aac3a9061281288859fd278d00ea848fc7253a53b8e12e578e1dcf176b4ab824fd977dd9d00fe1c644d1c83b2fb9cbf6fe97157f7ec36ae4491ce00589acd2404a2eeba16c1d2eba111806080e366300e8c7176ed2718dbf8fdfd48bb3898ab6b0d365b0322aac89562eb20518f27f51f4ee9a02c95e01e959f8a3a52a62de398387703dcf8c17e30a857d6f042a273ea54f5b686b0d83c242a2736ac45e9213d73a6ac3e18bb15016d9f9e8274239f20372290daaa50b8146c7a8bf1b151da1e3ab8d6366b655299b3302aa2b3be763a558172f183b9ef49f9bd423402d74db715c465cde710586c8c343d30abc860c1690ffafdc4caaf069ba2b47883a5af98f542e2c592d0e52fddb6f3d198e4fd8c00fb5294eb59709c928197f5cdeafe1e5a1b8e80a07a225cec02dde2d01556017cff634782415df3e0d2a366af18ee7d59610fbeffb8345b05546f71075899a23429760934844ae9fd56302dfa82e98a8be785f1c5be63885f1a2fd1ce066b240980d270630eb6fbc04d8389773651b293c143781305c42e5592d2802feb21684df8dddf3e437493d17d3b9cbdf47c1c916d7f2bd49ee3e766edbd626c47b3935b3603eaddaf1d7844a79b3163846ce49796c740021316f6c6ac83e076375c457b32bacabb4e21c7b99086b537768b9df5b8ebafbeba49b6a7f675f216904f2f790a0d90ebf52f9af807ca4ba4fde03334e500d21e419967a16f7d1300a15a76424279985d17286ff240ac9364c2623009f05c75f545bfba3e8baf202a79752fb46e21f792d96c75374a13fa33bdd787731835c83ec50be62dcf01e1cef40b75c12e728067f0d8c79f86bdbec7e63d8b157ec51a8d7876b5690efd30b98d76a073bfbe9485347582533dd4ea6ee29342876d1c53a45783ef7cad664090b57d866ccf481882059dbc98fe30e355a1684c1d3990ff36c555b85c0d52905d6a79b9ac60fae15d6902822f6f9a76572f46353e660d7da57abd11a71f3bc223dd3794e061e82130d9a7e452574838e49ef163cd19b0cad58fdf71b186875112af6f9281fd729e25f7314dad5f71321ac1b64936efd29253abe195e91d08b118bba2dd001287b9ddb54184cb7f20a77161599dd5b606bea6753b403de896716081afb6ca45dd1c8304df51be9b4fe53d2866c7318ad79db7bdb45ba6052e919cff7b5a11c4c274f1e7d6355034b909767bea8cf7de1ce7196d29eb5bc95a908283dda4b0fde95822093cc1ab63a35e1d40c1f4b231cac8c0359db70fc48f522ad94da4eaf4bfd93793ea2f383e80d14d15af940696c219c1bd8cc568d0abd11398622c040d733c5f81aad86abca86cd3f300a93832cb76fe0b5058492bf382675f859089e42831c53d1b8c675d36678979d1093f4728bb25cee192d3847db029864880302591ebdea08f4f6fe7e9ddfee962c008199a7ab5c38e093adf4411f62c0e3e8f4ec3d9f96ce4dc500ebdb2798f0bafae904da10fc171f69f13d7318516b67a1c414709e87bb4b981cff45d98cae9ae00a04fa5d6385f1fda248f126b46a97aae540020825d888c310c3f92176a9d279c8a044809726f9c6d3f86114f9317b53aacdfcdd75b0ce2aeac842b0b92ab8b7feb057a43c63b4a485967929496a8af1c25fff6e8564430facf472466d2476784ab74df515c150fa1be99d13fe388f77a03cb39148a389ef0036f89d9fa8845acfe5e481a7e4fe13b4d8160df767c37d1c36737b18df2cb0ddf710238c36e9a99b2d6162ea76410276416c1e2ffd4f11e221db4c5629cb516ee415e1524353092846220a5ccbd3f277f822039fa4197b3b5431f8ce16c2e60cfa14b36ebded00b859098f62a85106852ab1231ec238d4a775ed1dd411cf2c69ffd0550672490c6bffb504b28b014a354cae0a7a1cf1a50877d89c8f927a01270ce12e2842e058dd9d1ec8f1a8ef6177082014c6e1da7c984549c5405e1f02d0ddc1338ddaaf1424a1faafe3bb37dc1c60d51e29dccc27c1ac3240382e98555c265df7fe38d8a169adfae9b8e43aebc68bf3027af160f84ce4f5dd25a0c01af01d20b6c28bdf0870141b755050d4b848163613fcd1107536e6edbb270565f688b9a316c9be1cb78cf45b2b015f22425cf83d1413cb6685900b5daccecec7db62c3a444c89174fafe2484c042de9bbb9e64462f7625d117ef05575a1fa62d9e32f7423fc64e6ab89073ff2d64b382e1718cd10bffd54589b6a7d70eb86210858b84e64648450071c30213a0fe8739618fbd450d0198103d9087861566f436459362b131fe5138dec463b2596181b30df0e97d1b54c0e8f65e2367c45d41c7147b92603aa49174e96493238420fd739c8b473f1a6c805e1261159df95b55b0f25a0e1cef428912e19fed7d985152fcda7c71161273745a2f156839a1e0cdbcaeb1d830017bf30e89e12286e405a5ab3ffff3b6249eea7e5576a3d0b755193cf5de3be6739bcbde111746fa7509a98560f4b32a1207c5704e49ed9082181a85da3524fa0cd9182f20486abb7edf5e55cdda4e9d1544865b4f6d1623bd5b10037d2774bec886400abde4efe406439757c69333111234eb078dbcda1dfaf5799eb565f1ce2f74a19141f3deb171e82d2f07354d8d0a75afa7c749ace21add83097ef9ea0f43a8b46ebfe35abdd2c4346d8a7fbf3c2310e85b02b9665436bfba3b2f5913aefc1aefcf483464acc705c7bae16e3c0f1331e3e99164c0bfc273ff0aab9c9a290442ce82c1f7b59c47c52dc1dea65aea19c31df3d83e6cda11275929f992a3bf65da098a15462c7802c798085aa6da531755f409584f67e4e1fa3a8a1c49e8f9738e059da7773bc4764412155ce7695a06de4f09d47eaab8410674490f0f7e753c2de2728bfdead8365d01c0dc35a2e21da26c3f00a662c03d1fad9582802aa492de146a5cf7b33ae19c6c0888f7b3f10382783475be591fb2cb4413f10bba5ab8a3ca700ae606ab10023f3955c6e6db2d489c0396b3547b84e5dc9e3e93b43540c33ea6434772169e43110ed5e13cd4041a4b364800e252f48987f787cd25c49f8e8a541692de892522da6e4e96e64d267ea0c5efddb96fd3b98789005ef051d7448f1294ba417834ade96bd21f621e15cff207bc6b81b90b722d2914ac9a4419348b1c7c066b45af6a325e056cfb1703ca4768f96522dbcf8ea19c0509edc60b9987d845168dcec1c6cb6ef85169420baefc83e3689e63e456ebb533aa5b6c9b6d90cc033ee9c14a90c3ac7dda6ed2205c946255cc7d340c7a35687fb4ef5de1829bd3461e5a2faab8349276bda13d1462d49dcd5e6f9a36368520b6c7c1752b06ae0a0506565bc1a7d8c4c59e139b0d330d82aa9c303eea7cbb7fc2224d9f95b2287a681922425bf6ef7f743f71ed2fa2842381c1b2949a651e1bb299dac8e29ac9315b992664e5ba8a9b3ca3906b196efadbc05ca4657dd0ef2cfec897b01e70f868f1305e8b75da5bd94e47c1632094c7a36aca33f4d3372b2c50e55d2d15902fbd05a4e8fc9bb5d0f48e74acb2035095fdf5e00b5b74816f7a5147bd2209e1f86fd6e7380b6c7a0f21072aead00543fd3fa0d91069492434b5ec156790d9771280de3da610aee08984cfc1f81c066539a009ca24c0ad28eb8fd8d308648f00b4570c5b21f396d43d904b2cf1fd2707efd6b88459b769bbe2780a0e40eab6f75fbbd78a8ce2e314cc172913d58727400972c7f660514196631adf83977f9061a134732fdd95ef8d5d3947a8a01f0533d9f7ef930f5949c1c1c653c9fb90081643a100aa4ec653163313ac57aaaa1a61989b08984503a728d78353e244cf9808732c64cfc96aeb9e819bf10c0a671ef93e145144c4bf20f953671ab48d3f59bd3a25bb11813d634aa75a694919b6159de4f1e2baaa6c167aa26eaa59db15138e13329e5b1934f8955dde5366245d0247aded5fd1b78c249ce2b2f1e78687dc28da8854ecda9c496a1d4c19a0ede52513e61a5b394a643dcd6f130de3cdbd2db36030a7791baf39576bd2f54605a317833a6872380699eec46280a26304bc49a0f68c79db2fe44abd20b5bee690d92708963fec33f845e5720c7a25b7fce90e9102899172fab1ea26e6cc845c437f0e5ce793ec5d3948acb35f573c31e78e75b68fc76895e1583c710aef41aae5c90481424c02846be8668ae730f76587968037e34e522ebffeedcef3e81e0941e415c618ed6b810867c20facbfed55ca333d3a50c482609698f5b95d21e2279795295ce0e98d92fe1d2b43c42ed5559c6f4971ffae3329491473121aa7cb794ca00b7c3e7863507e82276fd36ffcf3c43d23e47ce5536bc76aa398368eeb579e7f11853b53920633bf35a45b9dc1152e54da494bbfc93077ee3099dd9a881850b02e4343e6772cb70201912893f7718cf3d9b7e0d0fe2e1ba6f1fdb2557db6f1f50a98771e423932f665fb9147123b4fba2853d93eb14152ccaf7aca70a2004ffd2457af6073b63c0efb1bbeb3940a0c916850fc1b63af7dff2b8650c02feff9be090222667949c1ffa8914d84037352820a9217cc6d8b5b86f52885eab7d6d47e267c0e4f355115ef7bec78eb1bb9b07f03537ac96e07a32024da4f61e32c6e1a0e6ca58ef7dabc94adf7f49167a946e1773314bd07caedea2b68ad18f9f0fc0d0cf941c6e7859e25aaaaeaee65f741bcbe44c1cc1f96ba18af294aee5af9593d04d4a99b71e196c51238d7dba3c1b70781a3f006e16e4f7c9a0dac3b453787c40f48eeae19d2c0a72762fa9a8e6b5aaddeb87c68c69e64f441d5ba7645531b431a787ffbecac74ed1de159491427b9b03e42b10fe1f98e8a4313f264d4fe067a05a3111e9f466f1738f37512359547155116970b042fc44b8ad98a7cf5dd00cb02e1524ff398f782f37222bdcb828b5dcfb4ea040ed8c8f3be119ed63625fb2e2a77380c84d607566fced8b0d3d8e909d9ff83f01527b190e40015a3d7def6d70f22fc9b4d8f06fdeee2c95c699ea8f8ecee88fa13c27cdf9c9fed4d38843f0019569ff7b02007bc0027f0a57c6b0b9e156f434a896d71b8b799efb621635a3512119ec00b23decb223eda213d5c2401dd1f14777cd6d612f0f7594d2cfc5701286f01cf5656ef4973e68f7df3e3b5215872b570d631eba74f4c55b27a4066f42fedf79141ddf98f44d7094dc562f62a590d88bd287429712f797d9658defa82229e4fd6f4f37b9f6b19b94470507f269b4a1473231d28e642946d95afd1923e082b35ea2f62f7f7b72cb5f365b08fc3bfe253d5247d6371ad6251a48eddb009177ae9cd062fbd258fbe07783d47fca0b290167da10536c29e4c86dc0877be242ca1b1ebba3fe8b526b6b5a6255f9aff4cecb7ece457020ddf108575355a98c2095bfce79a9b6a8d5c3ea400cbcf3f1c5228d4f14c4cb1c133e3ef9606daa69729bd87eede7202b55af964ec94c16100acf0045fceb020259acf5372628108a52dee8a37400289210ea94fc4d04320d0438e5446c61d9d015256d6afccb3cf1e1d92558cd7cebf73a10361e81e150ce610b06090910d19178cea3e3bc69cb9432958f2188617b97072f509c28a32a788615d4d591a752be53e55d89e80ec6bd72017be7dc9d99a3a2bca785c86ebc7539c6ddd18c1a0a37d8a918d316edddbf8238863eac1ffc39ff5017451e61d76e7d57a5c90a6e2b4964ce727c02bbe50e8104c0a87a31fc214b6f6a2e444fa3d5b96615262c059074eb41063bd0637c22c1591b5323e36d5acd765426b4f3b4fa2382a9cb45b9576207f780e82c5a4a3a204d4ffe24ac6810abbab362beb90ca637c6311a44ad31d6e3a868308e432feef18b2965854badd7ad634057f2e60258fabcd3c83d18de3031c4601783e6c8240085eabca90cec30013d00138685cc104c58e6d48e80b5582f4735a389cc3b781175b46dec8cb5249ffa38c7d54ceecd23ae4d3887cdd21b27d14982596004b9d17c6c69f79ad3cc750aa3b78bfd218170d5878c9332d345ba6d353cfc01edd2e133cf75325c79370a28117fa6ad8dbf04a0058a925c5f2ca117374c853e193c62355120f880ce444c81ac3d6558a8e9a345bf92aa75ea7d285e67bf01331d1561559f8502fe8d1c4b9150b91c5fefa5cb1159dd4ebdc25e9360a7d4e868a370b0fba1eda0da1014808d4e2ade1a5c0166f9076d99f36525000a638e03cc5936528b9341ff914e119da78f92a7355f42db985376707aff5609be44973ba5b926e2405c4715e456b9effc0fa6f000437a0bd37c04439958c647708f5b0d89acc5e245dc396aae5e61a3167916efeca48299130de7a9197ac5c91f41a2f8134a8d10ec0adca399237bfb1da227fc2ce8f6ee5a7b8707ca6cffed2a5bb6eeb8fbde91311dcc425d7a1c594a129963fbd366b34291492736a3e761f977c27e8140056287b33ac0a5d6cb9d5515c988fcfdf46b046e3800be37b85bd88877c4bb9e8ad1f1c2f1ce028010d6dddad64f7ec693353f5a69f86fb61b4fdeb60befc012fbf17250a793576c282e64ce1f1a8ae1b7cc1ca582f07dfb8a62a7f32d005592d1c18136f8ac60d1e0a0368da85a34337cb8fb61f9b6c93b945f0b694f8fd5c17dd004063c77a4235b56485926549450ce67d53211b80d8e22659d8ec39adc1533730387aa61745575304a44cdf5e46ff334bc1b5739f44e22955ea6cbf59ebe6450720a67099b41e4d3806a19b88b863742b1305c4fc80307f271380aeba22e949213da42eb6836f8a2477f025170295f4762ad8afc70384a829eafb2c330c0eef02e7b4a10f1880bb9a52d1b283d7ca2314450ff2974b5fb4246c2623531ccdab1a77c3b232427bc299b76f7380cde37298c1a684ac0e6349128a15afb4ee5fcb0524a99c8f4ce54a1c005e257baf2e31c4442d1cb1f42c336ee7d7d6b2c19625034a1ee973a46b2bebe839e776a66cebee1a741f094b7f10b58812d28508cf442c14e9e633d6e2640f79ff203d77caea167e7b7efe21ea52d2317df3898a0ebb0d3316f16bf92e3570d022b9bd5cbb277b709469ab03dc8981002862d232703c151039d50e1721e3f4b5e53bcc0dbee038c8f443ad769773ca6c5b8f0475dbad0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000aedd39c45321954a31a94232c1514fc2d632d6f1fe182f7f127654038a76d8f2e1cc07f39c70c7a87d578756db548ebbd6c17bb0319b5b490e2d39fe55652ea0d9e9b4cfc7cdfc182a0b5514d0e3a583b499ab342b4cc5d2536073110aa7cb50741f0550dec2646df9f3e68cc6ef12bb85f34e1e74ff59bfa84806e4e4f419f2192a4130a392ab8d1caea80ac2fc4b39d125fc1ef06374e463ae27414040c962ed1dc5d1756a69e788374dd3716c1efe9e40f48547ff520dddf440a12881aef1c28d881ae2867c83c54c39c0143afc5e89cbf4f921577f6fc3151729ff846d728b1e554b1f115db276ad487936bd19d596c7bf889237e3ec4e4c4ee72af76730a586f58b60b9ab4e8c87ca91344a7ca8c81171a1d291e6c7d9d6c3d31dc18c61ed6d19da10b0eeceb81f44426ddffba12d1135825ed3908cc0fd1648a04544e29cd60006839f4586321e6f3eeb651e71223a0e4f1cc3d7a921e78382210d00b23950215b85405f7a7c5381bc3bc4dd6a953cb37a74e20305c416d411ba1c9130829350bfa6aa9998057922d982b2ac617b501372b988de766b247b4e156fadc08b813a22d284a4b5b7b6974fd7fbf0f694155bb82010de7e31c079f2ae027772d09a35579c1fdbfeb9a6f97716a936cd98988291ac5ee87b7a719e371ddc52b0e06e29be3bad2ff8d82b19db6a5003d4defbeffca6ed2b4c85fb234f7e5e3ee1dc2e039ce4ea34aed5500432bfba4e67117442b46302b0b17cc8fec23c3983b076be47f23284da334b5d02a4a60124482dc41d70492cce003c854334bc988cf0a1129a2c793c04576e2011c4e39ccb6dca3df91755e24763597ba336ac3c2a000c897ac8508951277d9578d2838c0865ad9340bbb3fe17e00155ff6e5c172880c48fa15afb7eb2d2d45e987d8f930b389fa97d2a577f453ccc509d7cbf89c9a084bab654462daad3297491ad6005a08dcc5bfc71f27e86a7898c9d1971337890c6ea6968ed79a9eb09eacdb1f1b300b887eec3d79dad17899b959be2e2934c608cf74eb496ee77f75e21ec80abf489f18685aed9cfa5a65988d678f3a10b68f0385bfa953fa078638a4d0bb697e2f347323c1b7582f6512826a3ce6d437b4e50e44ca62869e9d1b4dd8e7cf50fae25136050ea4642142fb537485989ad3aea121992bf4432347ca2fdb606a89340a9fe2612c5644e0004b84207b92abca88702b3f75bc130abed3704261e0e0c7bc6172d315554f60b7be40ebd250f89ac7e4087e943193c8bccbb159cab9ef52af004c36575d4b33b50bd580a26363ea5c5023a3a37df568dede4fb1d2ee6000a8e1ce9c5377ab5861193c029db7661d01652dc1c49ee330a65454b2eede670e39cab7b88128c6c707605cddae6a2059abb924d73ca2402e2d2d09affe5f3cf580c40bcbfaca0216069ef0ed2455657a63921818c2a8fcd6ae7d39e8ebc4984b875f3820224b1bdbcfb17e4a89aa8fef4a88225426beca80ea5140730767b2d12dcbfe4c84971efc2cc1db4536244ef31ae2066ee0901d265ba71a95a5ebcf960b9ad56a91e125483048b1c6fc49939fa68d1f2cb09b504e77ffa01264c004d2973a5c30c2dfe6c8b20818d5ba4eee65e0362648eb1a5a239f933cb9b579d4e432d2d0f85ee0bf7fc223103fff7bf3f3c5410d4cfbe1f878e512b3f5ce26a09921f0df624b7105ef4b80095151d0480e421610fbb3b11018866d6a7c1e55fffee264d04cab0fd467157b452685717298fd57159b78d3457ebf31e21758e7443639bd1d102cfd70a40ade42024ab06a38f8c41cef250cbc560e0ba83ee7e92dbbd6166ca711736cd65146bba4bb11a4a13dbe0bbf839aee17e01a2566a72e383bb2c64737b264121468f6dbd60d4e229511dd026c8a44ee3f4fee5c3059c05a660ba74f407142c9a39ced7dad8e3ce277e518166aaf5d1c680e8ebe44da44f7cfc9d140de342682bd049cc4e1ec4243874a740000000000000000000000000000002d544172ff58c414aec63e4d5f1dfef43300000000000000000000000000000000001f9355535c4011f0431fd5d78385d70000000000000000000000000000005b0861b99d5f160f6230f9f890be2ebed600000000000000000000000000000000002712498aa068f693d353be01177e76000000000000000000000000000000a3ed814facb4a323ecf496cfe22111b98e000000000000000000000000000000000000453eacc387f1fc8f03e972e861df000000000000000000000000000000b562fd6643d726082f602da446b919e91b00000000000000000000000000000000002904ac9aa8f8c73d5d123d0daf07f500000000000000000000000000000024b01c7f327c090af5aabcc61b7744c5f600000000000000000000000000000000001af13e910c661bdaed7c407ef22832000000000000000000000000000000c5f99bec72c68505b53689e505ba5073a4000000000000000000000000000000000025d37be6c22499780a76ddead2c0f4000000000000000000000000000000bc96ca0405b11887d07dae6d902fc1af8000000000000000000000000000000000000570316b99804a92474966927a1eeb000000000000000000000000000000c51afbeae269b1d50b50ce246e56e43d710000000000000000000000000000000000112b77cb044c9747fe69f93a39abef000000000000000000000000000000cfeaaf59760d5bbc4655db3aadfea1a0aa000000000000000000000000000000000022c10efe9bc26d9b4ee0b1611e135a0000000000000000000000000000007582cf1ec23d97ba97718f2188b1c93371000000000000000000000000000000000013d8c781f121595d4e5598a4030a6c0000000000000000000000000000000a03577c6032b26766c15e3e08700548690000000000000000000000000000000000087663ffc7008c874adb639af87158000000000000000000000000000000a686745b827bfece761fe5806e76e35251000000000000000000000000000000000009e390b295946c5ac093093d77f7e1000000000000000000000000000000f48ac2601aa03434eb86554c6a549ed3e700000000000000000000000000000000001df06322fcd37d73fb3f73c03527310000000000000000000000000000001a6b37aabc3d0edb4464b9b50f0389ed38000000000000000000000000000000000022b9f7519f313e4fd502b95694aed90000000000000000000000000000001be2abb66660e897fe5f82fb08fc27315e00000000000000000000000000000000001f8501ccdd5f18745aa2201802eb02000000000000000000000000000000351aeb7da4935c09161342c7d209a8afaa0000000000000000000000000000000000225a2e0d33b9be5bb96ff1eb92d98f0000000000000000000000000000008cf2f296c72458fee42619fd34f507075500000000000000000000000000000000001e8fff6a9ae9dd278cd2aadf0e4594000000000000000000000000000000449ea257819728f0f882fa5d2e396d71a200000000000000000000000000000000000977abd3552057a0ea284e4663b71d000000000000000000000000000000065e14c6475e60e9d4861a4464e61f254700000000000000000000000000000000000c6c2d75a8189325b7db63beb40e1700000000000000000000000000000031bed94f48899760d0298269afec303b050000000000000000000000000000000000080a945d72442ba1d6e21ab43a96c1000000000000000000000000000000ed0fac5f4c80e355c0be8e66047830f59f000000000000000000000000000000000024e5c1a9a6375cc88f61d419b84c53000000000000000000000000000000f1ba93b6a3e6ef60273914a2ecfc75e8cf0000000000000000000000000000000000028e915ebf8361451cdeeb95c3abcc000000000000000000000000000000db1215215845e883a175c9a4a6f7263f4f00000000000000000000000000000000001bc43ab52f8e49eedd73ab963220fc000000000000000000000000000000b05cb9b046f7334960c1a24ca41f3d495000000000000000000000000000000000000b549fae7a60f066880d9168c3cde0000000000000000000000000000000e76311a28721dbb951d7c059ce215233a2000000000000000000000000000000000021e9da757f03a2b5aece398c8f1931000000000000000000000000000000c5c4ec6e9154a076fedc74df770919800f00000000000000000000000000000000002753f03c77aa03bb83ebc39588300f0000000000000000000000000000003406e0dd884841bca4da43bea6ed4d4bde000000000000000000000000000000000021e99f09e1ae95843b7164b7b096750000000000000000000000000000005ba04fffc36b84ebf25a49db84fe1bd39b00000000000000000000000000000000001e3e8423aa44343e612bb8ba4a089600000000000000000000000000000018cc12d2403c522eac722d7509ffce8f1b00000000000000000000000000000000001c6679071a1163f2ed8f2cdc8774500000000000000000000000000000009ec6c30ee33ffb79e6acceedb714f2544700000000000000000000000000000000000f58de5c741ddb445d68e0b103dd2e000000000000000000000000000000e11c50687be4e1f1604ee9049fe590f04d00000000000000000000000000000000001bf4b5bcfc56dc5d4e110fbdd2caec00000000000000000000000000000050564da2d316b539c0b90e67051b3aae240000000000000000000000000000000000024f95673a0d92228aea675d32ec1400000000000000000000000000000078e152955aec020cc07d64080144cd4e2100000000000000000000000000000000000bc4d829ac3c1e7e343fba8ce93546000000000000000000000000000000c2116b1ea40649ccff4f52eaaae87705d200000000000000000000000000000000000ec5de6da728c2e9464ff06bea8a2a000000000000000000000000000000dc164daa4520700db4a7ccd0da9dc15d0a00000000000000000000000000000000001ccc9883777dd2b7823c81951414cb000000000000000000000000000000a8e5dda2672f008588528bdf5755e82ff3000000000000000000000000000000000005b91f947e4eef5e064820f30652d30000000000000000000000000000003abdfc9d089300d182a4ee2a3de0ea5233000000000000000000000000000000000019c08834d097f3cab625642decf921000000000000000000000000000000e2f74bdf88bdc17abecf32d8f6b373ef08000000000000000000000000000000000015f00c84e4a25a8296891934c039820000000000000000000000000000009fbebd8a792cf6c8052ba4294d92698ae10000000000000000000000000000000000152eb9b5244862d97216b89e225ff000000000000000000000000000000022d241f5abdc2d4e66aa8d42553294dbef0000000000000000000000000000000000010bde456e78f9667d4a3626e3b979000000000000000000000000000000620da80ba4347c36225e7aeebb0931385300000000000000000000000000000000000708e7820ee84707ab5f837adf3dbd000000000000000000000000000000670890818a869ce4a038075ea47797966500000000000000000000000000000000000b084ac3e55bec281cfb12fd482407000000000000000000000000000000d1d5b9d7e75041e7ea386045e8119df15200000000000000000000000000000000001b24df43985e524d880ac83e3b903f0000000000000000000000000000001f90a496153cc5018f349982d7867d028700000000000000000000000000000000002329d015ee424259e29b2f0c9104de000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e287483358a5b7c81992f3fca50c2b348a00000000000000000000000000000000000ca6f20f3b3593f453aff040297f3200000000000000000000000000000063afa6e0000bd6381aa541e8116f7a71bd000000000000000000000000000000000015782cd812d4be6f6a93a0e3c4ec4b00000000000000000000000000000096877293c61a6caf329e011bc0fc2c9a4300000000000000000000000000000000000ed171e13cf1f16dc7c2abfe2712350000000000000000000000000000005f21b82d180b91c46a74d3f35bd0ed1e8c000000000000000000000000000000000003c25739dc307a886612157f3a34ec0000006b","aggregationObject":["0x000000000000000000000000000000000000000000000002e3059a3a513ebd21","0x00000000000000000000000000000000000000000000000acb31b01e879a4669","0x00000000000000000000000000000000000000000000000e4156ce7e68f8d05b","0x000000000000000000000000000000000000000000000000000207a06299fa9a","0x00000000000000000000000000000000000000000000000165ad30b03ce3eb2d","0x00000000000000000000000000000000000000000000000a3a7147ddb3b9458c","0x0000000000000000000000000000000000000000000000016e5155e9178c65c8","0x000000000000000000000000000000000000000000000000000068b23602e6fe","0x00000000000000000000000000000000000000000000000f6efd39e580a3e610","0x0000000000000000000000000000000000000000000000082e36b8da2b12bc49","0x000000000000000000000000000000000000000000000008ed75e19a27997c59","0x00000000000000000000000000000000000000000000000000017cef742b6868","0x000000000000000000000000000000000000000000000000fd810553a9e73f34","0x00000000000000000000000000000000000000000000000b145e0a2ee85822fc","0x000000000000000000000000000000000000000000000003b13582511a99c994","0x0000000000000000000000000000000000000000000000000002865bf9f95be9"]} \ No newline at end of file diff --git a/yarn-project/end-to-end/src/fixtures/index.ts b/yarn-project/end-to-end/src/fixtures/index.ts index 270da9ae54c..146faa68d45 100644 --- a/yarn-project/end-to-end/src/fixtures/index.ts +++ b/yarn-project/end-to-end/src/fixtures/index.ts @@ -1,4 +1,3 @@ export * from './fixtures.js'; export * from './logging.js'; export * from './utils.js'; -export * from './watcher.js'; diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index f462b270171..4a5400f53eb 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -2,6 +2,7 @@ import { SchnorrAccountContractArtifact, getSchnorrAccount } from '@aztec/accoun import { type Archiver, createArchiver } from '@aztec/archiver'; import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node'; import { + AnvilTestWatcher, type AztecAddress, type AztecNode, BatchCall, @@ -44,7 +45,6 @@ import { deployCanonicalRouter, getPrivateKeyFromIndex, } from './utils.js'; -import { Watcher } from './watcher.js'; export type SubsystemsContext = { anvil: Anvil; @@ -55,7 +55,7 @@ export type SubsystemsContext = { pxe: PXEService; deployL1ContractsValues: DeployL1Contracts; proverNode: ProverNode; - watcher: Watcher; + watcher: AnvilTestWatcher; }; type SnapshotEntry = { @@ -312,6 +312,13 @@ async function setupFromFresh( aztecNodeConfig.l1Contracts = deployL1ContractsValues.l1ContractAddresses; aztecNodeConfig.l1PublishRetryIntervalMS = 100; + const watcher = new AnvilTestWatcher( + new EthCheatCodes(aztecNodeConfig.l1RpcUrl), + deployL1ContractsValues.l1ContractAddresses.rollupAddress, + deployL1ContractsValues.publicClient, + ); + await watcher.start(); + const acvmConfig = await getACVMConfig(logger); if (acvmConfig) { aztecNodeConfig.acvmWorkingDirectory = acvmConfig.acvmWorkingDirectory; @@ -335,13 +342,6 @@ async function setupFromFresh( aztecNode, ); - const watcher = new Watcher( - new EthCheatCodes(aztecNodeConfig.l1RpcUrl), - deployL1ContractsValues.l1ContractAddresses.rollupAddress, - deployL1ContractsValues.publicClient, - ); - watcher.start(); - logger.verbose('Creating pxe...'); const pxeConfig = getPXEServiceConfig(); pxeConfig.dataDirectory = statePath; @@ -417,12 +417,12 @@ async function setupFromState(statePath: string, logger: Logger): Promise + (numberOfAccounts: number, logger: DebugLogger, waitUntilProven = true) => async ({ pxe }: { pxe: PXE }) => { // Generate account keys. const accountKeys: [Fr, GrumpkinScalar][] = Array.from({ length: numberOfAccounts }).map(_ => [ @@ -487,7 +487,7 @@ export const addAccounts = logger.verbose('Deploying accounts...'); const txs = await Promise.all(accountManagers.map(account => account.deploy())); - await Promise.all(txs.map(tx => tx.wait({ interval: 0.1, proven: true }))); + await Promise.all(txs.map(tx => tx.wait({ interval: 0.1, proven: waitUntilProven }))); return { accountKeys }; }; @@ -498,12 +498,16 @@ export const addAccounts = * @param sender - Wallet to send the deployment tx. * @param accountsToDeploy - Which accounts to publicly deploy. */ -export async function publicDeployAccounts(sender: Wallet, accountsToDeploy: (CompleteAddress | AztecAddress)[]) { +export async function publicDeployAccounts( + sender: Wallet, + accountsToDeploy: (CompleteAddress | AztecAddress)[], + waitUntilProven = true, +) { const accountAddressesToDeploy = accountsToDeploy.map(a => ('address' in a ? a.address : a)); const instances = await Promise.all(accountAddressesToDeploy.map(account => sender.getContractInstance(account))); const batch = new BatchCall(sender, [ (await registerContractClass(sender, SchnorrAccountContractArtifact)).request(), ...instances.map(instance => deployInstance(sender, instance!).request()), ]); - await batch.send().wait({ proven: true }); + await batch.send().wait({ proven: waitUntilProven }); } diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 52322c1d86c..94c65a0c088 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -3,6 +3,7 @@ import { createAccounts, getDeployedTestAccountsWallets } from '@aztec/accounts/ import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node'; import { type AccountWalletWithSecretKey, + AnvilTestWatcher, AztecAddress, type AztecNode, BatchCall, @@ -39,7 +40,7 @@ import { computeContractAddressFromInstance, getContractClassFromArtifact, } from '@aztec/circuits.js'; -import { NULL_KEY } from '@aztec/ethereum'; +import { NULL_KEY, isAnvilTestChain } from '@aztec/ethereum'; import { bufferAsFields } from '@aztec/foundation/abi'; import { makeBackoff, retry, retryUntil } from '@aztec/foundation/retry'; import { @@ -89,7 +90,6 @@ import { MNEMONIC } from './fixtures.js'; import { getACVMConfig } from './get_acvm_config.js'; import { getBBConfig } from './get_bb_config.js'; import { isMetricsLoggingRequested, setupMetricsLogger } from './logging.js'; -import { Watcher } from './watcher.js'; export { deployAndInitializeTokenAndBridgeContracts } from '../shared/cross_chain_test_harness.js'; @@ -349,7 +349,7 @@ export async function setup( let anvil: Anvil | undefined; if (!config.l1RpcUrl) { - if (chain.id != foundry.id) { + if (!isAnvilTestChain(chain.id)) { throw new Error(`No ETHEREUM_HOST set but non anvil chain requested`); } if (PXE_URL) { @@ -406,6 +406,14 @@ export async function setup( config.l1Contracts = deployL1ContractsValues.l1ContractAddresses; + const watcher = new AnvilTestWatcher( + new EthCheatCodes(config.l1RpcUrl), + deployL1ContractsValues.l1ContractAddresses.rollupAddress, + deployL1ContractsValues.publicClient, + ); + + await watcher.start(); + // Run the test with validators enabled const validatorPrivKey = getPrivateKeyFromIndex(1); config.validatorPrivateKey = `0x${validatorPrivKey!.toString('hex')}`; @@ -457,17 +465,6 @@ export async function setup( ); } - const watcher = new Watcher( - new EthCheatCodes(config.l1RpcUrl), - deployL1ContractsValues.l1ContractAddresses.rollupAddress, - deployL1ContractsValues.publicClient, - ); - - // If we are NOT using wall time, we should start the watcher to jump in time as needed. - if (!opts.l1BlockTime) { - watcher.start(); - } - const wallets = numberOfAccounts > 0 ? await createAccounts(pxe, numberOfAccounts) : []; const cheatCodes = CheatCodes.create(config.l1RpcUrl, pxe!); diff --git a/yarn-project/end-to-end/src/public-testnet/e2e_public_testnet_transfer.test.ts b/yarn-project/end-to-end/src/public-testnet/e2e_public_testnet_transfer.test.ts index 8c3828f6497..1ecc615eed5 100644 --- a/yarn-project/end-to-end/src/public-testnet/e2e_public_testnet_transfer.test.ts +++ b/yarn-project/end-to-end/src/public-testnet/e2e_public_testnet_transfer.test.ts @@ -64,6 +64,7 @@ describe(`deploys and transfers a private only token`, () => { interval: 0.1, proven: true, provenTimeout: 600, + timeout: 300, }); logger.info(`Accounts deployed, deploying token.`); @@ -86,6 +87,7 @@ describe(`deploys and transfers a private only token`, () => { .deployed({ proven: true, provenTimeout: 600, + timeout: 300, }); logger.info(`Performing transfer.`); @@ -93,7 +95,7 @@ describe(`deploys and transfers a private only token`, () => { await token.methods .transfer(transferValue, deployerWallet.getAddress(), recipientWallet.getAddress(), deployerWallet.getAddress()) .send() - .wait({ proven: true, provenTimeout: 600 }); + .wait({ proven: true, provenTimeout: 600, timeout: 300 }); logger.info(`Transfer completed`); diff --git a/yarn-project/end-to-end/src/sample-dapp/connect.mjs b/yarn-project/end-to-end/src/sample-dapp/connect.mjs index 6486f7447a1..560a337ba33 100644 --- a/yarn-project/end-to-end/src/sample-dapp/connect.mjs +++ b/yarn-project/end-to-end/src/sample-dapp/connect.mjs @@ -5,8 +5,8 @@ const { PXE_URL = 'http://localhost:8080' } = process.env; async function main() { const pxe = createPXEClient(PXE_URL); - const { chainId } = await pxe.getNodeInfo(); - console.log(`Connected to chain ${chainId}`); + const { l1ChainId } = await pxe.getNodeInfo(); + console.log(`Connected to chain ${l1ChainId}`); } main().catch(err => { diff --git a/yarn-project/end-to-end/src/spartan/transfer.test.ts b/yarn-project/end-to-end/src/spartan/transfer.test.ts index df8993a99bd..c47a4e8876e 100644 --- a/yarn-project/end-to-end/src/spartan/transfer.test.ts +++ b/yarn-project/end-to-end/src/spartan/transfer.test.ts @@ -3,7 +3,6 @@ import { type AccountWallet, type AccountWalletWithSecretKey, type AztecAddress, - type CompleteAddress, ExtendedNote, Fr, Note, @@ -17,7 +16,7 @@ import { TokenContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; -import { addAccounts, publicDeployAccounts } from '../fixtures/snapshot_manager.js'; +import { addAccounts } from '../fixtures/snapshot_manager.js'; const { PXE_URL } = process.env; if (!PXE_URL) { @@ -65,52 +64,93 @@ describe('token transfer test', () => { const TOKEN_SYMBOL = 'USD'; const TOKEN_DECIMALS = 18n; const MINT_AMOUNT = 20n; + + const WALLET_COUNT = 1; + const ROUNDS = 5n; + let pxe: PXE; let wallets: AccountWalletWithSecretKey[]; - let completeAddresses: CompleteAddress[]; + let recipientWallet: AccountWalletWithSecretKey; let tokenAddress: AztecAddress; let tokenAtWallet0: TokenContract; + beforeAll(async () => { + expect(ROUNDS).toBeLessThanOrEqual(MINT_AMOUNT); + + // My guess is that is never proven so if we are waiting for it to prove we wait forever? pxe = await createCompatibleClient(PXE_URL, logger); - const { accountKeys } = await addAccounts(3, logger)({ pxe }); + { + const { accountKeys } = await addAccounts(1, logger, false)({ pxe }); + const accountManagers = accountKeys.map(ak => getSchnorrAccount(pxe, ak[0], ak[1], 1)); + + const partialAddress = accountManagers[0].getCompleteAddress().partialAddress; + await pxe.registerAccount(accountKeys[0][0], partialAddress); + recipientWallet = await accountManagers[0].getWallet(); + logger.verbose(`Recipient Wallet address: ${recipientWallet.getAddress()} registered`); + } + + const { accountKeys } = await addAccounts(Number(WALLET_COUNT), logger, false)({ pxe }); const accountManagers = accountKeys.map(ak => getSchnorrAccount(pxe, ak[0], ak[1], 1)); - wallets = await Promise.all(accountManagers.map(a => a.getWallet())); - completeAddresses = await pxe.getRegisteredAccounts(); - wallets.forEach((w, i) => logger.verbose(`Wallet ${i} address: ${w.getAddress()}`)); - await publicDeployAccounts(wallets[0], completeAddresses.slice(0, 2)); + + wallets = await Promise.all( + accountManagers.map(async (a, i) => { + const partialAddress = a.getCompleteAddress().partialAddress; + await pxe.registerAccount(accountKeys[i][0], partialAddress); + const wallet = await a.getWallet(); + logger.verbose(`Wallet ${i} address: ${wallet.getAddress()} registered`); + return wallet; + }), + ); logger.verbose(`Deploying TokenContract...`); const tokenContract = await TokenContract.deploy( wallets[0], - completeAddresses[0], + wallets[0].getAddress(), TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS, ) .send() - .deployed(); + .deployed({ timeout: 600 }); tokenAddress = tokenContract.address; tokenAtWallet0 = await TokenContract.at(tokenAddress, wallets[0]); - logger.verbose(`Minting ${MINT_AMOUNT} publicly...`); - await tokenAtWallet0.methods.mint_public(completeAddresses[0].address, MINT_AMOUNT).send().wait(); - - logger.verbose(`Minting ${MINT_AMOUNT} privately...`); - const secret = Fr.random(); - const secretHash = computeSecretHash(secret); - const receipt = await tokenAtWallet0.methods.mint_private(MINT_AMOUNT, secretHash).send().wait(); - - await addPendingShieldNoteToPXE({ - amount: MINT_AMOUNT, - secretHash, - txHash: receipt.txHash, - accountAddress: completeAddresses[0].address, - assetAddress: tokenAddress, - wallet: wallets[0], + logger.verbose(`Minting ${MINT_AMOUNT} public assets to the ${wallets.length} wallets...`); + + await Promise.all( + wallets.map(w => tokenAtWallet0.methods.mint_public(w.getAddress(), MINT_AMOUNT).send().wait({ timeout: 600 })), + ); + + logger.verbose(`Minting ${MINT_AMOUNT} private assets to the ${wallets.length} wallets...`); + const secrets: Fr[] = wallets.map(() => Fr.random()); + + const txs = await Promise.all( + wallets.map((w, i) => + tokenAtWallet0.methods.mint_private(MINT_AMOUNT, computeSecretHash(secrets[i])).send().wait({ timeout: 600 }), + ), + ); + + wallets.forEach(async (wallet, i) => { + await addPendingShieldNoteToPXE({ + amount: MINT_AMOUNT, + secretHash: computeSecretHash(secrets[i]), + txHash: txs[i].txHash, + accountAddress: wallet.getAddress(), + assetAddress: tokenAddress, + wallet: wallet, + }); }); - const txClaim = tokenAtWallet0.methods.redeem_shield(completeAddresses[0].address, MINT_AMOUNT, secret).send(); - await txClaim.wait({ debug: true }); + + await Promise.all( + wallets.map(async (w, i) => + (await TokenContract.at(tokenAddress, w)).methods + .redeem_shield(w.getAddress(), MINT_AMOUNT, secrets[i]) + .send() + .wait({ timeout: 600 }), + ), + ); + logger.verbose(`Minting complete.`); }); @@ -119,34 +159,54 @@ describe('token transfer test', () => { expect(name).toBe(TOKEN_NAME); }); - it('can transfer 1 publicly', async () => { + it('can transfer 1 token privately and publicly', async () => { + const recipient = recipientWallet.getAddress(); const transferAmount = 1n; - const numTransfers = MINT_AMOUNT / transferAmount; - const initialBalance = await tokenAtWallet0.methods.balance_of_public(completeAddresses[0].address).simulate(); - expect(initialBalance).toBeGreaterThanOrEqual(transferAmount); - for (let i = 1n; i <= numTransfers; i++) { - await tokenAtWallet0.methods - .transfer_public(completeAddresses[0].address, completeAddresses[1].address, transferAmount, 0) - .send() - .wait(); - } - const finalBalance0 = await tokenAtWallet0.methods.balance_of_public(completeAddresses[0].address).simulate(); - expect(finalBalance0).toBe(0n); - const finalBalance1 = await tokenAtWallet0.methods.balance_of_public(completeAddresses[1].address).simulate(); - expect(finalBalance1).toBe(MINT_AMOUNT); - }); - it('can transfer 1 privately', async () => { - const transferAmount = 1n; - const numTransfers = MINT_AMOUNT / transferAmount; - const initialBalance = await tokenAtWallet0.methods.balance_of_private(completeAddresses[0].address).simulate(); - expect(initialBalance).toBeGreaterThanOrEqual(transferAmount); - for (let i = 1n; i <= numTransfers; i++) { - await tokenAtWallet0.methods.transfer(completeAddresses[1].address, transferAmount).send().wait(); + wallets.forEach(async w => { + expect(MINT_AMOUNT).toBe( + await (await TokenContract.at(tokenAddress, w)).methods.balance_of_private(w.getAddress()).simulate(), + ); + expect(MINT_AMOUNT).toBe(await tokenAtWallet0.methods.balance_of_public(w.getAddress()).simulate()); + }); + + expect(0n).toBe( + await (await TokenContract.at(tokenAddress, recipientWallet)).methods.balance_of_private(recipient).simulate(), + ); + expect(0n).toBe(await tokenAtWallet0.methods.balance_of_public(recipient).simulate()); + + // For each round, make both private and public transfers + for (let i = 1n; i <= ROUNDS; i++) { + const txs = await Promise.all([ + ...wallets.map(async w => + (await TokenContract.at(tokenAddress, w)).methods.transfer(recipient, transferAmount), + ), + ...wallets.map(async w => + ( + await TokenContract.at(tokenAddress, w) + ).methods.transfer_public(w.getAddress(), recipient, transferAmount, 0), + ), + ]); + + txs.forEach(async t => await t.prove()); + + await Promise.all(txs.map(t => t.send().wait({ timeout: 600 }))); } - const finalBalance0 = await tokenAtWallet0.methods.balance_of_private(completeAddresses[0].address).simulate(); - expect(finalBalance0).toBe(0n); - const finalBalance1 = await tokenAtWallet0.methods.balance_of_private(completeAddresses[1].address).simulate(); - expect(finalBalance1).toBe(MINT_AMOUNT); + + wallets.forEach(async w => { + expect(MINT_AMOUNT - ROUNDS * transferAmount).toBe( + await (await TokenContract.at(tokenAddress, w)).methods.balance_of_private(w.getAddress()).simulate(), + ); + expect(MINT_AMOUNT - ROUNDS * transferAmount).toBe( + await tokenAtWallet0.methods.balance_of_public(w.getAddress()).simulate(), + ); + }); + + expect(ROUNDS * transferAmount * BigInt(wallets.length)).toBe( + await (await TokenContract.at(tokenAddress, recipientWallet)).methods.balance_of_private(recipient).simulate(), + ); + expect(ROUNDS * transferAmount * BigInt(wallets.length)).toBe( + await tokenAtWallet0.methods.balance_of_public(recipient).simulate(), + ); }); }); diff --git a/yarn-project/ethereum/src/constants.ts b/yarn-project/ethereum/src/constants.ts index 92e0b01c9d3..c1f4b34d732 100644 --- a/yarn-project/ethereum/src/constants.ts +++ b/yarn-project/ethereum/src/constants.ts @@ -1,3 +1,4 @@ import { type Hex } from 'viem'; export const NULL_KEY: Hex = `0x${'0000000000000000000000000000000000000000000000000000000000000000'}`; +export const AZTEC_TEST_CHAIN_ID = 677692; diff --git a/yarn-project/ethereum/src/deploy_l1_contracts.ts b/yarn-project/ethereum/src/deploy_l1_contracts.ts index ac0e11a03be..eaf4f83f13b 100644 --- a/yarn-project/ethereum/src/deploy_l1_contracts.ts +++ b/yarn-project/ethereum/src/deploy_l1_contracts.ts @@ -26,6 +26,7 @@ import { import { type HDAccount, type PrivateKeyAccount, mnemonicToAccount, privateKeyToAccount } from 'viem/accounts'; import { foundry } from 'viem/chains'; +import { isAnvilTestChain } from './ethereum_chain.js'; import { type L1ContractAddresses } from './l1_contract_addresses.js'; /** @@ -167,7 +168,7 @@ export const deployL1Contracts = async ( }; return await (await fetch(rpcUrl, content)).json(); }; - if (chain.id == foundry.id) { + if (isAnvilTestChain(chain.id)) { const interval = 12; const res = await rpcCall('anvil_setBlockTimestampInterval', [interval]); if (res.error) { @@ -260,7 +261,7 @@ export const deployL1Contracts = async ( `Initialized Gas Portal at ${feeJuicePortalAddress} to bridge between L1 ${feeJuiceAddress} to L2 ${args.l2FeeJuiceAddress}`, ); - if (chain.id == foundry.id) { + if (isAnvilTestChain(chain.id)) { // @note We make a time jump PAST the very first slot to not have to deal with the edge case of the first slot. // The edge case being that the genesis block is already occupying slot 0, so we cannot have another block. try { diff --git a/yarn-project/ethereum/src/ethereum_chain.ts b/yarn-project/ethereum/src/ethereum_chain.ts index 0f8d401a01d..7fc9dd092cf 100644 --- a/yarn-project/ethereum/src/ethereum_chain.ts +++ b/yarn-project/ethereum/src/ethereum_chain.ts @@ -1,4 +1,7 @@ import { type Chain } from 'viem'; +import { foundry } from 'viem/chains'; + +import { AZTEC_TEST_CHAIN_ID } from './constants.js'; /** * Interface containing the connection and chain properties to interact with a blockchain. @@ -14,3 +17,55 @@ export interface EthereumChain { */ rpcUrl: string; } + +/** + * Helper function to create an instance of Aztec Chain from an rpc url and api key. + * @param rpcUrl - The rpc url of the chain or a chain identifier (e.g. 'testnet') + * @param apiKey - An optional API key for the chain client. + */ +export function createEthereumChain(rpcUrl: string, _chainId: number | string): EthereumChain { + let chainId: number; + if (typeof _chainId === 'string') { + chainId = +_chainId; + } else { + chainId = _chainId; + } + if (chainId) { + return { + chainInfo: { + id: chainId, + name: 'Ethereum', + rpcUrls: { + default: { + http: [rpcUrl], + }, + }, + nativeCurrency: { + decimals: 18, + name: 'Ether', + symbol: 'ETH', + }, + }, + rpcUrl, + }; + } else { + return { + chainInfo: foundry, + rpcUrl, + }; + } +} + +/** + * Helper function to determine if a chain id is an instance of Anvil + */ +export function isAnvilTestChain(_chainId: number | string): boolean { + let chainId: number; + if (typeof _chainId === 'string') { + chainId = +_chainId; + } else { + chainId = _chainId; + } + const testChains = [foundry.id, AZTEC_TEST_CHAIN_ID]; + return testChains.includes(chainId); +} diff --git a/yarn-project/ethereum/src/index.ts b/yarn-project/ethereum/src/index.ts index c136dcdb263..aac126e1108 100644 --- a/yarn-project/ethereum/src/index.ts +++ b/yarn-project/ethereum/src/index.ts @@ -1,46 +1,5 @@ -import { foundry } from 'viem/chains'; - -import { type EthereumChain } from './ethereum_chain.js'; - export * from './constants.js'; export * from './deploy_l1_contracts.js'; export * from './l1_contract_addresses.js'; export * from './l1_reader.js'; - -/** - * Helper function to create an instance of Aztec Chain from an rpc url and api key. - * @param rpcUrl - The rpc url of the chain or a chain identifier (e.g. 'testnet') - * @param apiKey - An optional API key for the chain client. - */ -export function createEthereumChain(rpcUrl: string, _chainId: number | string): EthereumChain { - let chainId: number; - if (typeof _chainId === 'string') { - chainId = +_chainId; - } else { - chainId = _chainId; - } - if (chainId) { - return { - chainInfo: { - id: chainId, - name: 'Ethereum', - rpcUrls: { - default: { - http: [rpcUrl], - }, - }, - nativeCurrency: { - decimals: 18, - name: 'Ether', - symbol: 'ETH', - }, - }, - rpcUrl, - }; - } else { - return { - chainInfo: foundry, - rpcUrl, - }; - } -} +export * from './ethereum_chain.js'; diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index 43f908c5d72..ebd360bcf5a 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -48,6 +48,7 @@ export type EnvVar = | 'ARCHIVER_POLLING_INTERVAL_MS' | 'ARCHIVER_VIEM_POLLING_INTERVAL_MS' | 'ARCHIVER_MAX_LOGS' + | 'ARCHIVER_L1_START_BLOCK' | 'SEQ_TX_POLLING_INTERVAL_MS' | 'SEQ_MAX_TX_PER_BLOCK' | 'SEQ_MIN_TX_PER_BLOCK' diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index e84b9efbc7f..be9f0a8552d 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -34,7 +34,6 @@ import { KeyValidationRequestAndGenerator, type L1_TO_L2_MSG_TREE_HEIGHT, L2ToL1Message, - type LeafDataReadHint, LogHash, MAX_ENCRYPTED_LOGS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, @@ -98,8 +97,8 @@ import { PublicCallStackItemCompressed, type PublicCircuitPublicInputs, type PublicDataHint, + type PublicDataLeafHint, PublicDataRead, - type PublicDataReadRequestHints, type PublicDataTreeLeaf, type PublicDataTreeLeafPreimage, PublicDataUpdateRequest, @@ -133,6 +132,7 @@ import { type TreeLeafReadRequestHint, TxContext, type TxRequest, + VERIFICATION_KEY_LENGTH_IN_FIELDS, type VerificationKeyAsFields, } from '@aztec/circuits.js'; import { toBufferBE } from '@aztec/foundation/bigint-buffer'; @@ -170,7 +170,6 @@ import type { KeyValidationRequestAndGenerator as KeyValidationRequestAndGeneratorNoir, KeyValidationRequest as KeyValidationRequestsNoir, L2ToL1Message as L2ToL1MessageNoir, - LeafDataReadHint as LeafDataReadHintNoir, LogHash as LogHashNoir, MaxBlockNumber as MaxBlockNumberNoir, MembershipWitness as MembershipWitnessNoir, @@ -219,8 +218,8 @@ import type { PublicCallStackItem as PublicCallStackItemNoir, PublicCircuitPublicInputs as PublicCircuitPublicInputsNoir, PublicDataHint as PublicDataHintNoir, + PublicDataLeafHint as PublicDataLeafHintNoir, PublicDataRead as PublicDataReadNoir, - PublicDataReadRequestHints as PublicDataReadRequestHintsNoir, PublicDataTreeLeaf as PublicDataTreeLeafNoir, PublicDataTreeLeafPreimage as PublicDataTreeLeafPreimageNoir, PublicDataUpdateRequest as PublicDataUpdateRequestNoir, @@ -252,6 +251,7 @@ import type { TreeLeafReadRequest as TreeLeafReadRequestNoir, TxContext as TxContextNoir, TxRequest as TxRequestNoir, + VerificationKey as VerificationKeyNoir, } from './types/index.js'; /* eslint-disable camelcase */ @@ -1069,7 +1069,11 @@ export function mapPublicDataUpdateRequestToNoir( * @returns The parsed public data read. */ export function mapPublicDataReadFromNoir(publicDataRead: PublicDataReadNoir): PublicDataRead { - return new PublicDataRead(mapFieldFromNoir(publicDataRead.leaf_slot), mapFieldFromNoir(publicDataRead.value)); + return new PublicDataRead( + mapFieldFromNoir(publicDataRead.leaf_slot), + mapFieldFromNoir(publicDataRead.value), + mapNumberFromNoir(publicDataRead.counter), + ); } /** @@ -1081,6 +1085,7 @@ export function mapPublicDataReadToNoir(publicDataRead: PublicDataRead): PublicD return { leaf_slot: mapFieldToNoir(publicDataRead.leafSlot), value: mapFieldToNoir(publicDataRead.value), + counter: mapNumberToNoir(publicDataRead.counter), }; } @@ -1098,13 +1103,6 @@ function mapPendingReadHintToNoir(hint: PendingReadHint): PendingReadHintNoir { }; } -function mapLeafDataReadHintToNoir(hint: LeafDataReadHint): LeafDataReadHintNoir { - return { - read_request_index: mapNumberToNoir(hint.readRequestIndex), - data_hint_index: mapNumberToNoir(hint.dataHintIndex), - }; -} - function mapTreeLeafReadRequestHintToNoir( hint: TreeLeafReadRequestHint, ): TreeLeafReadRequestHintNoir { @@ -1196,11 +1194,10 @@ function mapPublicDataHintToNoir(hint: PublicDataHint): PublicDataHintNoir { }; } -function mapPublicDataReadRequestHintsToNoir(hints: PublicDataReadRequestHints): PublicDataReadRequestHintsNoir { +function mapPublicDataLeafHintToNoir(hint: PublicDataLeafHint): PublicDataLeafHintNoir { return { - read_request_statuses: mapTuple(hints.readRequestStatuses, mapReadRequestStatusToNoir), - pending_read_hints: mapTuple(hints.pendingReadHints, mapPendingReadHintToNoir), - leaf_data_read_hints: mapTuple(hints.leafDataReadHints, mapLeafDataReadHintToNoir), + preimage: mapPublicDataTreePreimageToNoir(hint.preimage), + membership_witness: mapMembershipWitnessToNoir(hint.membershipWitness), }; } @@ -1580,9 +1577,12 @@ export function mapKernelDataToNoir(kernelData: KernelData): KernelDataNoir { }; } -export function mapVerificationKeyToNoir(key: VerificationKeyAsFields) { +export function mapVerificationKeyToNoir(key: VerificationKeyAsFields): VerificationKeyNoir { + if (key.key.length !== VERIFICATION_KEY_LENGTH_IN_FIELDS) { + throw new Error(`Expected ${VERIFICATION_KEY_LENGTH_IN_FIELDS} fields, got ${key.key.length}`); + } return { - key: mapTuple(key.key, mapFieldToNoir), + key: mapTuple(key.key as Tuple, mapFieldToNoir), hash: mapFieldToNoir(key.hash), }; } @@ -1799,8 +1799,7 @@ export function mapPublicKernelTailCircuitPrivateInputsToNoir( inputs.l1ToL2MsgReadRequestHints, (hint: TreeLeafReadRequestHint) => mapTreeLeafReadRequestHintToNoir(hint), ), - public_data_hints: mapTuple(inputs.publicDataHints, mapPublicDataHintToNoir), - public_data_read_request_hints: mapPublicDataReadRequestHintsToNoir(inputs.publicDataReadRequestHints), + public_data_hints: mapTuple(inputs.publicDataHints, mapPublicDataLeafHintToNoir), start_state: mapPartialStateReferenceToNoir(inputs.startState), }; } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 45490c6332f..bb336b19735 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -27,7 +27,6 @@ import { } from '@aztec/circuit-types/interfaces'; import { type CircuitName } from '@aztec/circuit-types/stats'; import { - AGGREGATION_OBJECT_LENGTH, AvmCircuitInputs, type BaseOrMergeRollupPublicInputs, BaseParityInputs, @@ -63,7 +62,7 @@ import { sha256Trunc } from '@aztec/foundation/crypto'; import { AbortError } from '@aztec/foundation/error'; import { createDebugLogger } from '@aztec/foundation/log'; import { promiseWithResolvers } from '@aztec/foundation/promise'; -import { BufferReader, type Tuple } from '@aztec/foundation/serialize'; +import { type Tuple } from '@aztec/foundation/serialize'; import { pushTestData } from '@aztec/foundation/testing'; import { elapsed } from '@aztec/foundation/timer'; import { getVKIndex, getVKSiblingPath, getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; @@ -455,12 +454,7 @@ export class ProvingOrchestrator implements BlockProver { }) public async finaliseBlock() { try { - if ( - !this.provingState || - !this.provingState.blockRootRollupPublicInputs || - !this.provingState.finalProof || - !this.provingState.finalAggregationObject - ) { + if (!this.provingState || !this.provingState.blockRootRollupPublicInputs || !this.provingState.finalProof) { throw new Error(`Invalid proving state, a block must be proven before it can be finalised`); } if (this.provingState.block) { @@ -503,11 +497,13 @@ export class ProvingOrchestrator implements BlockProver { const blockResult: ProvingBlockResult = { proof: this.provingState.finalProof, - aggregationObject: this.provingState.finalAggregationObject, + aggregationObject: this.provingState.finalProof.extractAggregationObject(), block: l2Block, }; pushTestData('blockResults', { + proverId: this.proverId.toString(), + vkTreeRoot: getVKTreeRoot().toString(), block: l2Block.toString(), proof: this.provingState.finalProof.toString(), aggregationObject: blockResult.aggregationObject.map(x => x.toString()), @@ -878,10 +874,6 @@ export class ProvingOrchestrator implements BlockProver { ), result => { provingState.blockRootRollupPublicInputs = result.inputs; - provingState.finalAggregationObject = extractAggregationObject( - result.proof.binaryProof, - result.verificationKey.numPublicInputs, - ); provingState.finalProof = result.proof.binaryProof; const provingResult: ProvingResult = { @@ -1155,15 +1147,3 @@ export class ProvingOrchestrator implements BlockProver { ); } } - -function extractAggregationObject(proof: Proof, numPublicInputs: number): Fr[] { - const buffer = proof.buffer.subarray( - Fr.SIZE_IN_BYTES * (numPublicInputs - AGGREGATION_OBJECT_LENGTH), - Fr.SIZE_IN_BYTES * numPublicInputs, - ); - // TODO(#7159): Remove the following workaround - if (buffer.length === 0) { - return Array.from({ length: AGGREGATION_OBJECT_LENGTH }, () => Fr.ZERO); - } - return BufferReader.asReader(buffer).readArray(AGGREGATION_OBJECT_LENGTH, Fr); -} diff --git a/yarn-project/prover-client/src/orchestrator/proving-state.ts b/yarn-project/prover-client/src/orchestrator/proving-state.ts index 380720d09c9..4aaa96abd63 100644 --- a/yarn-project/prover-client/src/orchestrator/proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/proving-state.ts @@ -47,7 +47,6 @@ export class ProvingState { private rootParityInputs: Array | undefined> = []; private finalRootParityInputs: RootParityInput | undefined; public blockRootRollupPublicInputs: BlockRootOrBlockMergePublicInputs | undefined; - public finalAggregationObject: Fr[] | undefined; public finalProof: Proof | undefined; public block: L2Block | undefined; private txs: TxProvingState[] = []; diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts index 82f466b1151..6722ded9101 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts @@ -13,6 +13,10 @@ interface MockAvailabilityOracleWrite { publish: (args: readonly [`0x${string}`], options: { account: PrivateKeyAccount }) => Promise<`0x${string}`>; } +interface MockAvailabilityOracleEstimate { + publish: (args: readonly [`0x${string}`], options: { account: PrivateKeyAccount }) => Promise; +} + interface MockAvailabilityOracleRead { isAvailable: (args: readonly [`0x${string}`]) => Promise; } @@ -21,6 +25,7 @@ class MockAvailabilityOracle { constructor( public write: MockAvailabilityOracleWrite, public simulate: MockAvailabilityOracleWrite, + public estimateGas: MockAvailabilityOracleEstimate, public read: MockAvailabilityOracleRead, ) {} } @@ -69,6 +74,7 @@ describe('L1Publisher', () => { let availabilityOracleRead: MockProxy; let availabilityOracleWrite: MockProxy; let availabilityOracleSimulate: MockProxy; + let availabilityOracleEstimate: MockProxy; let availabilityOracle: MockAvailabilityOracle; let publicClient: MockProxy; @@ -88,6 +94,8 @@ describe('L1Publisher', () => { let publisher: L1Publisher; + const GAS_GUESS = 300_000n; + beforeEach(() => { l2Block = L2Block.random(42); @@ -97,7 +105,7 @@ describe('L1Publisher', () => { body = l2Block.body.toBuffer(); processTxHash = `0x${Buffer.from('txHashProcess').toString('hex')}`; // random tx hash - proposeTxHash = `0x${Buffer.from('txHashpropose').toString('hex')}`; // random tx hash + proposeTxHash = `0x${Buffer.from('txHashPropose').toString('hex')}`; // random tx hash processTxReceipt = { transactionHash: processTxHash, @@ -118,9 +126,11 @@ describe('L1Publisher', () => { availabilityOracleWrite = mock(); availabilityOracleRead = mock(); availabilityOracleSimulate = mock(); + availabilityOracleEstimate = mock(); availabilityOracle = new MockAvailabilityOracle( availabilityOracleWrite, availabilityOracleSimulate, + availabilityOracleEstimate, availabilityOracleRead, ); @@ -146,6 +156,7 @@ describe('L1Publisher', () => { account = (publisher as any)['account']; rollupContractRead.getCurrentSlot.mockResolvedValue(l2Block.header.globalVariables.slotNumber.toBigInt()); + availabilityOracleEstimate.publish.mockResolvedValueOnce(GAS_GUESS); publicClient.getBlock.mockResolvedValue({ timestamp: 12n }); }); @@ -153,6 +164,7 @@ describe('L1Publisher', () => { rollupContractRead.archive.mockResolvedValue(l2Block.header.lastArchive.root.toString() as `0x${string}`); rollupContractWrite.propose.mockResolvedValueOnce(proposeTxHash); rollupContractSimulate.propose.mockResolvedValueOnce(proposeTxHash); + publicClient.getTransactionReceipt.mockResolvedValueOnce(proposeTxReceipt); const result = await publisher.processL2Block(l2Block); @@ -163,12 +175,13 @@ describe('L1Publisher', () => { `0x${header.toString('hex')}`, `0x${archive.toString('hex')}`, `0x${blockHash.toString('hex')}`, + [], `0x${body.toString('hex')}`, ] as const; - if (!L1Publisher.SKIP_SIMULATION) { - expect(rollupContractSimulate.propose).toHaveBeenCalledWith(args, { account: account }); - } - expect(rollupContractWrite.propose).toHaveBeenCalledWith(args, { account: account }); + expect(rollupContractWrite.propose).toHaveBeenCalledWith(args, { + account: account, + gas: L1Publisher.PROPOSE_GAS_GUESS + GAS_GUESS * 2n, + }); expect(publicClient.getTransactionReceipt).toHaveBeenCalledWith({ hash: proposeTxHash }); }); @@ -186,11 +199,9 @@ describe('L1Publisher', () => { `0x${header.toString('hex')}`, `0x${archive.toString('hex')}`, `0x${blockHash.toString('hex')}`, + [], ] as const; - if (!L1Publisher.SKIP_SIMULATION) { - expect(rollupContractSimulate.propose).toHaveBeenCalledWith(args, { account }); - } - expect(rollupContractWrite.propose).toHaveBeenCalledWith(args, { account }); + expect(rollupContractWrite.propose).toHaveBeenCalledWith(args, { account, gas: L1Publisher.PROPOSE_GAS_GUESS }); expect(publicClient.getTransactionReceipt).toHaveBeenCalledWith({ hash: processTxHash }); }); diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index ad5e091ab34..4f30bef3215 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -97,15 +97,6 @@ export type L1SubmitProofArgs = { * Adapted from https://github.com/AztecProtocol/aztec2-internal/blob/master/falafel/src/rollup_publisher.ts. */ export class L1Publisher { - // @note If we want to simulate in the future, we have to skip the viem simulations and use `reads` instead - // This is because the viem simulations are not able to simulate the future, only the current state. - // This means that we will be simulating as if `block.timestamp` is the same for the next block - // as for the last block. - // Nevertheless, it can be quite useful for figuring out why exactly the transaction is failing - // as a middle ground right now, we will be skipping the simulation and just sending the transaction - // but only after we have done a successful run of the `validateHeader` for the timestamp in the future. - public static SKIP_SIMULATION = true; - private interruptibleSleep = new InterruptibleSleep(); private sleepTimeMs: number; private interrupted = false; @@ -123,6 +114,8 @@ export class L1Publisher { private publicClient: PublicClient; private account: PrivateKeyAccount; + public static PROPOSE_GAS_GUESS: bigint = 500_000n; + constructor(config: TxSenderConfig & PublisherConfig, client: TelemetryClient) { this.sleepTimeMs = config?.l1PublishRetryIntervalMS ?? 60_000; this.metrics = new L1PublisherMetrics(client, 'L1Publisher'); @@ -332,7 +325,7 @@ export class L1Publisher { archive: archiveRoot.toBuffer(), proverId: proverId.toBuffer(), aggregationObject: serializeToBuffer(aggregationObject), - proof: proof.toBuffer(), + proof: proof.withoutPublicInputs(), }; // Process block @@ -400,11 +393,9 @@ export class L1Publisher { `0x${proof.toString('hex')}`, ] as const; - if (!L1Publisher.SKIP_SIMULATION) { - await this.rollupContract.simulate.submitBlockRootProof(args, { - account: this.account, - }); - } + await this.rollupContract.simulate.submitBlockRootProof(args, { + account: this.account, + }); return await this.rollupContract.write.submitBlockRootProof(args, { account: this.account, @@ -439,36 +430,20 @@ export class L1Publisher { private async sendProposeWithoutBodyTx(encodedData: L1ProcessArgs): Promise { if (!this.interrupted) { try { - if (encodedData.attestations) { - const attestations = encodedData.attestations.map(attest => attest.toViemSignature()); - const args = [ - `0x${encodedData.header.toString('hex')}`, - `0x${encodedData.archive.toString('hex')}`, - `0x${encodedData.blockHash.toString('hex')}`, - attestations, - ] as const; - - if (!L1Publisher.SKIP_SIMULATION) { - await this.rollupContract.simulate.propose(args, { account: this.account }); - } - - return await this.rollupContract.write.propose(args, { - account: this.account, - }); - } else { - const args = [ - `0x${encodedData.header.toString('hex')}`, - `0x${encodedData.archive.toString('hex')}`, - `0x${encodedData.blockHash.toString('hex')}`, - ] as const; - - if (!L1Publisher.SKIP_SIMULATION) { - await this.rollupContract.simulate.propose(args, { account: this.account }); - } - return await this.rollupContract.write.propose(args, { - account: this.account, - }); - } + const attestations = encodedData.attestations + ? encodedData.attestations.map(attest => attest.toViemSignature()) + : []; + const args = [ + `0x${encodedData.header.toString('hex')}`, + `0x${encodedData.archive.toString('hex')}`, + `0x${encodedData.blockHash.toString('hex')}`, + attestations, + ] as const; + + return await this.rollupContract.write.propose(args, { + account: this.account, + gas: L1Publisher.PROPOSE_GAS_GUESS, + }); } catch (err) { this.log.error(`Rollup publish failed`, err); return undefined; @@ -479,43 +454,33 @@ export class L1Publisher { private async sendProposeTx(encodedData: L1ProcessArgs): Promise { if (!this.interrupted) { try { - if (encodedData.attestations) { - const attestations = encodedData.attestations.map(attest => attest.toViemSignature()); - const args = [ - `0x${encodedData.header.toString('hex')}`, - `0x${encodedData.archive.toString('hex')}`, - `0x${encodedData.blockHash.toString('hex')}`, - attestations, - `0x${encodedData.body.toString('hex')}`, - ] as const; - - if (!L1Publisher.SKIP_SIMULATION) { - await this.rollupContract.simulate.propose(args, { - account: this.account, - }); - } - - return await this.rollupContract.write.propose(args, { - account: this.account, - }); - } else { - const args = [ - `0x${encodedData.header.toString('hex')}`, - `0x${encodedData.archive.toString('hex')}`, - `0x${encodedData.blockHash.toString('hex')}`, - `0x${encodedData.body.toString('hex')}`, - ] as const; - - if (!L1Publisher.SKIP_SIMULATION) { - await this.rollupContract.simulate.propose(args, { - account: this.account, - }); - } - - return await this.rollupContract.write.propose(args, { - account: this.account, - }); - } + const publishGas = await this.availabilityOracleContract.estimateGas.publish([ + `0x${encodedData.body.toString('hex')}`, + ]); + const min = (a: bigint, b: bigint) => (a > b ? b : a); + + // @note We perform this guesstimate instead of the usual `gasEstimate` since + // viem will use the current state to simulate against, which means that + // we will fail estimation in the case where we are simulating for the + // first ethereum block within our slot (as current time is not in the + // slot yet). + const gasGuesstimate = min(publishGas * 2n + L1Publisher.PROPOSE_GAS_GUESS, 15_000_000n); + + const attestations = encodedData.attestations + ? encodedData.attestations.map(attest => attest.toViemSignature()) + : []; + const args = [ + `0x${encodedData.header.toString('hex')}`, + `0x${encodedData.archive.toString('hex')}`, + `0x${encodedData.blockHash.toString('hex')}`, + attestations, + `0x${encodedData.body.toString('hex')}`, + ] as const; + + return await this.rollupContract.write.propose(args, { + account: this.account, + gas: gasGuesstimate, + }); } catch (err) { this.log.error(`Rollup publish failed`, err); return undefined; diff --git a/yarn-project/simulator/src/avm/avm_execution_environment.ts b/yarn-project/simulator/src/avm/avm_execution_environment.ts index 27a1e32ec9c..99c55567942 100644 --- a/yarn-project/simulator/src/avm/avm_execution_environment.ts +++ b/yarn-project/simulator/src/avm/avm_execution_environment.ts @@ -1,15 +1,14 @@ import { FunctionSelector, type GlobalVariables, type Header } from '@aztec/circuits.js'; -import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; export class AvmContextInputs { static readonly SIZE = 2; - constructor(private argsHash: Fr, private isStaticCall: boolean) {} + constructor(private calldataSize: Fr, private isStaticCall: boolean) {} public toFields(): Fr[] { - return [this.argsHash, new Fr(this.isStaticCall)]; + return [this.calldataSize, new Fr(this.isStaticCall)]; } } @@ -33,7 +32,7 @@ export class AvmExecutionEnvironment { ) { // We encode some extra inputs (AvmContextInputs) in calldata. // This will have to go once we move away from one proof per call. - const inputs = new AvmContextInputs(computeVarArgsHash(calldata), isStaticCall).toFields(); + const inputs = new AvmContextInputs(new Fr(calldata.length), isStaticCall).toFields(); this.calldata = [...inputs, ...calldata]; } diff --git a/yarn-project/simulator/src/avm/avm_gas.ts b/yarn-project/simulator/src/avm/avm_gas.ts index f7d4787885f..43f5d48d782 100644 --- a/yarn-project/simulator/src/avm/avm_gas.ts +++ b/yarn-project/simulator/src/avm/avm_gas.ts @@ -57,20 +57,33 @@ export const GasDimensions = ['l2Gas', 'daGas'] as const; /** Base gas costs for each instruction. Additional gas cost may be added on top due to memory or storage accesses, etc. */ const BaseGasCosts: Record = { - [Opcode.ADD]: makeCost(c.AVM_ADD_BASE_L2_GAS, 0), - [Opcode.SUB]: makeCost(c.AVM_SUB_BASE_L2_GAS, 0), - [Opcode.MUL]: makeCost(c.AVM_MUL_BASE_L2_GAS, 0), - [Opcode.DIV]: makeCost(c.AVM_DIV_BASE_L2_GAS, 0), - [Opcode.FDIV]: makeCost(c.AVM_FDIV_BASE_L2_GAS, 0), - [Opcode.EQ]: makeCost(c.AVM_EQ_BASE_L2_GAS, 0), - [Opcode.LT]: makeCost(c.AVM_LT_BASE_L2_GAS, 0), - [Opcode.LTE]: makeCost(c.AVM_LTE_BASE_L2_GAS, 0), - [Opcode.AND]: makeCost(c.AVM_AND_BASE_L2_GAS, 0), - [Opcode.OR]: makeCost(c.AVM_OR_BASE_L2_GAS, 0), - [Opcode.XOR]: makeCost(c.AVM_XOR_BASE_L2_GAS, 0), + [Opcode.ADD_8]: makeCost(c.AVM_ADD_BASE_L2_GAS, 0), + [Opcode.ADD_16]: makeCost(c.AVM_ADD_BASE_L2_GAS, 0), + [Opcode.SUB_8]: makeCost(c.AVM_SUB_BASE_L2_GAS, 0), + [Opcode.SUB_16]: makeCost(c.AVM_SUB_BASE_L2_GAS, 0), + [Opcode.MUL_8]: makeCost(c.AVM_MUL_BASE_L2_GAS, 0), + [Opcode.MUL_16]: makeCost(c.AVM_MUL_BASE_L2_GAS, 0), + [Opcode.DIV_8]: makeCost(c.AVM_DIV_BASE_L2_GAS, 0), + [Opcode.DIV_16]: makeCost(c.AVM_DIV_BASE_L2_GAS, 0), + [Opcode.FDIV_8]: makeCost(c.AVM_FDIV_BASE_L2_GAS, 0), + [Opcode.FDIV_16]: makeCost(c.AVM_FDIV_BASE_L2_GAS, 0), + [Opcode.EQ_8]: makeCost(c.AVM_EQ_BASE_L2_GAS, 0), + [Opcode.EQ_16]: makeCost(c.AVM_EQ_BASE_L2_GAS, 0), + [Opcode.LT_8]: makeCost(c.AVM_LT_BASE_L2_GAS, 0), + [Opcode.LT_16]: makeCost(c.AVM_LT_BASE_L2_GAS, 0), + [Opcode.LTE_8]: makeCost(c.AVM_LTE_BASE_L2_GAS, 0), + [Opcode.LTE_16]: makeCost(c.AVM_LTE_BASE_L2_GAS, 0), + [Opcode.AND_8]: makeCost(c.AVM_AND_BASE_L2_GAS, 0), + [Opcode.AND_16]: makeCost(c.AVM_AND_BASE_L2_GAS, 0), + [Opcode.OR_8]: makeCost(c.AVM_OR_BASE_L2_GAS, 0), + [Opcode.OR_16]: makeCost(c.AVM_OR_BASE_L2_GAS, 0), + [Opcode.XOR_8]: makeCost(c.AVM_XOR_BASE_L2_GAS, 0), + [Opcode.XOR_16]: makeCost(c.AVM_XOR_BASE_L2_GAS, 0), [Opcode.NOT]: makeCost(c.AVM_NOT_BASE_L2_GAS, 0), - [Opcode.SHL]: makeCost(c.AVM_SHL_BASE_L2_GAS, 0), - [Opcode.SHR]: makeCost(c.AVM_SHR_BASE_L2_GAS, 0), + [Opcode.SHL_8]: makeCost(c.AVM_SHL_BASE_L2_GAS, 0), + [Opcode.SHL_16]: makeCost(c.AVM_SHL_BASE_L2_GAS, 0), + [Opcode.SHR_8]: makeCost(c.AVM_SHR_BASE_L2_GAS, 0), + [Opcode.SHR_16]: makeCost(c.AVM_SHR_BASE_L2_GAS, 0), [Opcode.CAST]: makeCost(c.AVM_CAST_BASE_L2_GAS, 0), [Opcode.ADDRESS]: makeCost(c.AVM_ADDRESS_BASE_L2_GAS, 0), [Opcode.STORAGEADDRESS]: makeCost(c.AVM_STORAGEADDRESS_BASE_L2_GAS, 0), @@ -83,18 +96,21 @@ const BaseGasCosts: Record = { [Opcode.VERSION]: makeCost(c.AVM_VERSION_BASE_L2_GAS, 0), [Opcode.BLOCKNUMBER]: makeCost(c.AVM_BLOCKNUMBER_BASE_L2_GAS, 0), [Opcode.TIMESTAMP]: makeCost(c.AVM_TIMESTAMP_BASE_L2_GAS, 0), - [Opcode.COINBASE]: makeCost(c.AVM_COINBASE_BASE_L2_GAS, 0), - [Opcode.BLOCKL2GASLIMIT]: makeCost(c.AVM_BLOCKL2GASLIMIT_BASE_L2_GAS, 0), - [Opcode.BLOCKDAGASLIMIT]: makeCost(c.AVM_BLOCKDAGASLIMIT_BASE_L2_GAS, 0), [Opcode.CALLDATACOPY]: makeCost(c.AVM_CALLDATACOPY_BASE_L2_GAS, 0), [Opcode.L2GASLEFT]: makeCost(c.AVM_L2GASLEFT_BASE_L2_GAS, 0), [Opcode.DAGASLEFT]: makeCost(c.AVM_DAGASLEFT_BASE_L2_GAS, 0), - [Opcode.JUMP]: makeCost(c.AVM_JUMP_BASE_L2_GAS, 0), - [Opcode.JUMPI]: makeCost(c.AVM_JUMPI_BASE_L2_GAS, 0), + [Opcode.JUMP_16]: makeCost(c.AVM_JUMP_BASE_L2_GAS, 0), + [Opcode.JUMPI_16]: makeCost(c.AVM_JUMPI_BASE_L2_GAS, 0), [Opcode.INTERNALCALL]: makeCost(c.AVM_INTERNALCALL_BASE_L2_GAS, 0), [Opcode.INTERNALRETURN]: makeCost(c.AVM_INTERNALRETURN_BASE_L2_GAS, 0), - [Opcode.SET]: makeCost(c.AVM_SET_BASE_L2_GAS, 0), - [Opcode.MOV]: makeCost(c.AVM_MOV_BASE_L2_GAS, 0), + [Opcode.SET_8]: makeCost(c.AVM_SET_BASE_L2_GAS, 0), + [Opcode.SET_16]: makeCost(c.AVM_SET_BASE_L2_GAS, 0), + [Opcode.SET_32]: makeCost(c.AVM_SET_BASE_L2_GAS, 0), + [Opcode.SET_64]: makeCost(c.AVM_SET_BASE_L2_GAS, 0), + [Opcode.SET_128]: makeCost(c.AVM_SET_BASE_L2_GAS, 0), + [Opcode.SET_FF]: makeCost(c.AVM_SET_BASE_L2_GAS, 0), + [Opcode.MOV_8]: makeCost(c.AVM_MOV_BASE_L2_GAS, 0), + [Opcode.MOV_16]: makeCost(c.AVM_MOV_BASE_L2_GAS, 0), [Opcode.CMOV]: makeCost(c.AVM_CMOV_BASE_L2_GAS, 0), [Opcode.SLOAD]: makeCost(c.AVM_SLOAD_BASE_L2_GAS, 0), [Opcode.SSTORE]: makeCost(c.AVM_SSTORE_BASE_L2_GAS, 0), @@ -125,20 +141,33 @@ const BaseGasCosts: Record = { }; const DynamicGasCosts: Record = { - [Opcode.ADD]: makeCost(c.AVM_ADD_DYN_L2_GAS, 0), - [Opcode.SUB]: makeCost(c.AVM_SUB_DYN_L2_GAS, 0), - [Opcode.MUL]: makeCost(c.AVM_MUL_DYN_L2_GAS, 0), - [Opcode.DIV]: makeCost(c.AVM_DIV_DYN_L2_GAS, 0), - [Opcode.FDIV]: makeCost(c.AVM_FDIV_DYN_L2_GAS, 0), - [Opcode.EQ]: makeCost(c.AVM_EQ_DYN_L2_GAS, 0), - [Opcode.LT]: makeCost(c.AVM_LT_DYN_L2_GAS, 0), - [Opcode.LTE]: makeCost(c.AVM_LTE_DYN_L2_GAS, 0), - [Opcode.AND]: makeCost(c.AVM_AND_DYN_L2_GAS, 0), - [Opcode.OR]: makeCost(c.AVM_OR_DYN_L2_GAS, 0), - [Opcode.XOR]: makeCost(c.AVM_XOR_DYN_L2_GAS, 0), + [Opcode.ADD_8]: makeCost(c.AVM_ADD_DYN_L2_GAS, 0), + [Opcode.ADD_16]: makeCost(c.AVM_ADD_DYN_L2_GAS, 0), + [Opcode.SUB_8]: makeCost(c.AVM_SUB_DYN_L2_GAS, 0), + [Opcode.SUB_16]: makeCost(c.AVM_SUB_DYN_L2_GAS, 0), + [Opcode.MUL_8]: makeCost(c.AVM_MUL_DYN_L2_GAS, 0), + [Opcode.MUL_16]: makeCost(c.AVM_MUL_DYN_L2_GAS, 0), + [Opcode.DIV_8]: makeCost(c.AVM_DIV_DYN_L2_GAS, 0), + [Opcode.DIV_16]: makeCost(c.AVM_DIV_DYN_L2_GAS, 0), + [Opcode.FDIV_8]: makeCost(c.AVM_FDIV_DYN_L2_GAS, 0), + [Opcode.FDIV_16]: makeCost(c.AVM_FDIV_DYN_L2_GAS, 0), + [Opcode.EQ_8]: makeCost(c.AVM_EQ_DYN_L2_GAS, 0), + [Opcode.EQ_16]: makeCost(c.AVM_EQ_DYN_L2_GAS, 0), + [Opcode.LT_8]: makeCost(c.AVM_LT_DYN_L2_GAS, 0), + [Opcode.LT_16]: makeCost(c.AVM_LT_DYN_L2_GAS, 0), + [Opcode.LTE_8]: makeCost(c.AVM_LTE_DYN_L2_GAS, 0), + [Opcode.LTE_16]: makeCost(c.AVM_LTE_DYN_L2_GAS, 0), + [Opcode.AND_8]: makeCost(c.AVM_AND_DYN_L2_GAS, 0), + [Opcode.AND_16]: makeCost(c.AVM_AND_DYN_L2_GAS, 0), + [Opcode.OR_8]: makeCost(c.AVM_OR_DYN_L2_GAS, 0), + [Opcode.OR_16]: makeCost(c.AVM_OR_DYN_L2_GAS, 0), + [Opcode.XOR_8]: makeCost(c.AVM_XOR_DYN_L2_GAS, 0), + [Opcode.XOR_16]: makeCost(c.AVM_XOR_DYN_L2_GAS, 0), [Opcode.NOT]: makeCost(c.AVM_NOT_DYN_L2_GAS, 0), - [Opcode.SHL]: makeCost(c.AVM_SHL_DYN_L2_GAS, 0), - [Opcode.SHR]: makeCost(c.AVM_SHR_DYN_L2_GAS, 0), + [Opcode.SHL_8]: makeCost(c.AVM_SHL_DYN_L2_GAS, 0), + [Opcode.SHL_16]: makeCost(c.AVM_SHL_DYN_L2_GAS, 0), + [Opcode.SHR_8]: makeCost(c.AVM_SHR_DYN_L2_GAS, 0), + [Opcode.SHR_16]: makeCost(c.AVM_SHR_DYN_L2_GAS, 0), [Opcode.CAST]: makeCost(c.AVM_CAST_DYN_L2_GAS, 0), [Opcode.ADDRESS]: makeCost(c.AVM_ADDRESS_DYN_L2_GAS, 0), [Opcode.STORAGEADDRESS]: makeCost(c.AVM_STORAGEADDRESS_DYN_L2_GAS, 0), @@ -151,18 +180,21 @@ const DynamicGasCosts: Record = { [Opcode.VERSION]: makeCost(c.AVM_VERSION_DYN_L2_GAS, 0), [Opcode.BLOCKNUMBER]: makeCost(c.AVM_BLOCKNUMBER_DYN_L2_GAS, 0), [Opcode.TIMESTAMP]: makeCost(c.AVM_TIMESTAMP_DYN_L2_GAS, 0), - [Opcode.COINBASE]: makeCost(c.AVM_COINBASE_DYN_L2_GAS, 0), - [Opcode.BLOCKL2GASLIMIT]: makeCost(c.AVM_BLOCKL2GASLIMIT_DYN_L2_GAS, 0), - [Opcode.BLOCKDAGASLIMIT]: makeCost(c.AVM_BLOCKDAGASLIMIT_DYN_L2_GAS, 0), [Opcode.CALLDATACOPY]: makeCost(c.AVM_CALLDATACOPY_DYN_L2_GAS, 0), [Opcode.L2GASLEFT]: makeCost(c.AVM_L2GASLEFT_DYN_L2_GAS, 0), [Opcode.DAGASLEFT]: makeCost(c.AVM_DAGASLEFT_DYN_L2_GAS, 0), - [Opcode.JUMP]: makeCost(c.AVM_JUMP_DYN_L2_GAS, 0), - [Opcode.JUMPI]: makeCost(c.AVM_JUMPI_DYN_L2_GAS, 0), + [Opcode.JUMP_16]: makeCost(c.AVM_JUMP_DYN_L2_GAS, 0), + [Opcode.JUMPI_16]: makeCost(c.AVM_JUMPI_DYN_L2_GAS, 0), [Opcode.INTERNALCALL]: makeCost(c.AVM_INTERNALCALL_DYN_L2_GAS, 0), [Opcode.INTERNALRETURN]: makeCost(c.AVM_INTERNALRETURN_DYN_L2_GAS, 0), - [Opcode.SET]: makeCost(c.AVM_SET_DYN_L2_GAS, 0), - [Opcode.MOV]: makeCost(c.AVM_MOV_DYN_L2_GAS, 0), + [Opcode.SET_8]: makeCost(c.AVM_SET_DYN_L2_GAS, 0), + [Opcode.SET_16]: makeCost(c.AVM_SET_DYN_L2_GAS, 0), + [Opcode.SET_32]: makeCost(c.AVM_SET_DYN_L2_GAS, 0), + [Opcode.SET_64]: makeCost(c.AVM_SET_DYN_L2_GAS, 0), + [Opcode.SET_128]: makeCost(c.AVM_SET_DYN_L2_GAS, 0), + [Opcode.SET_FF]: makeCost(c.AVM_SET_DYN_L2_GAS, 0), + [Opcode.MOV_8]: makeCost(c.AVM_MOV_DYN_L2_GAS, 0), + [Opcode.MOV_16]: makeCost(c.AVM_MOV_DYN_L2_GAS, 0), [Opcode.CMOV]: makeCost(c.AVM_CMOV_DYN_L2_GAS, 0), [Opcode.SLOAD]: makeCost(c.AVM_SLOAD_DYN_L2_GAS, 0), [Opcode.SSTORE]: makeCost(c.AVM_SSTORE_DYN_L2_GAS, 0), diff --git a/yarn-project/simulator/src/avm/avm_memory_types.ts b/yarn-project/simulator/src/avm/avm_memory_types.ts index 59eb9a98553..c85f920b7be 100644 --- a/yarn-project/simulator/src/avm/avm_memory_types.ts +++ b/yarn-project/simulator/src/avm/avm_memory_types.ts @@ -350,7 +350,7 @@ export class TaggedMemory implements TaggedMemoryInterface { } // Truncates the value to fit the type. - public static integralFromTag(v: bigint | number, tag: TypeTag): IntegralValue { + public static buildFromTagTruncating(v: bigint | number, tag: TypeTag): MemoryValue { v = BigInt(v); switch (tag) { case TypeTag.UINT8: @@ -363,8 +363,10 @@ export class TaggedMemory implements TaggedMemoryInterface { return new Uint64(v & ((1n << 64n) - 1n)); case TypeTag.UINT128: return new Uint128(v & ((1n << 128n) - 1n)); + case TypeTag.FIELD: + return new Field(v); default: - throw new Error(`${TypeTag[tag]} is not a valid integral type.`); + throw new Error(`${TypeTag[tag]} is not a valid tag.`); } } diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index c4c179ccbe6..6bca1202516 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -32,8 +32,9 @@ import { } from './fixtures/index.js'; import { type HostStorage } from './journal/host_storage.js'; import { type AvmPersistableStateManager } from './journal/journal.js'; -import { Add, CalldataCopy, Return } from './opcodes/index.js'; +import { Add, CalldataCopy, Return, Set } from './opcodes/index.js'; import { encodeToBytecode } from './serialization/bytecode_serialization.js'; +import { Opcode } from './serialization/instruction_serialization.js'; import { mockGetBytecode, mockGetContractInstance, @@ -52,8 +53,16 @@ describe('AVM simulator: injected bytecode', () => { beforeAll(() => { calldata = [new Fr(1), new Fr(2)]; bytecode = encodeToBytecode([ - new CalldataCopy(/*indirect=*/ 0, /*cdOffset=*/ adjustCalldataIndex(0), /*copySize=*/ 2, /*dstOffset=*/ 0), - new Add(/*indirect=*/ 0, TypeTag.FIELD, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2), + new Set(/*indirect*/ 0, TypeTag.UINT32, /*value*/ adjustCalldataIndex(0), /*dstOffset*/ 0).as( + Opcode.SET_8, + Set.wireFormat8, + ), + new Set(/*indirect*/ 0, TypeTag.UINT32, /*value*/ 2, /*dstOffset*/ 1).as(Opcode.SET_8, Set.wireFormat8), + new CalldataCopy(/*indirect=*/ 0, /*cdOffset=*/ 0, /*copySize=*/ 1, /*dstOffset=*/ 0), + new Add(/*indirect=*/ 0, TypeTag.FIELD, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2).as( + Opcode.ADD_8, + Add.wireFormat8, + ), new Return(/*indirect=*/ 0, /*returnOffset=*/ 2, /*copySize=*/ 1), ]); }); @@ -68,7 +77,6 @@ describe('AVM simulator: injected bytecode', () => { expect(results.reverted).toBe(false); expect(results.output).toEqual([new Fr(3)]); - expect(context.machineState.l2GasLeft).toEqual(99999100); }); it('Should halt if runs out of gas', async () => { @@ -226,6 +234,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { ['set_opcode_u64', 1n << 60n], ['set_opcode_small_field', 0x001234567890abcdef1234567890abcdefn], ['set_opcode_big_field', 0x991234567890abcdef1234567890abcdefn], + ['set_opcode_really_big_field', 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdefn], ])('SET functions', (name: string, res: bigint) => { it(`function '${name}'`, async () => { const context = initContext(); diff --git a/yarn-project/simulator/src/avm/bytecode_utils.ts b/yarn-project/simulator/src/avm/bytecode_utils.ts index 52b0f31032e..68ed5117941 100644 --- a/yarn-project/simulator/src/avm/bytecode_utils.ts +++ b/yarn-project/simulator/src/avm/bytecode_utils.ts @@ -1,13 +1,13 @@ import { promisify } from 'util'; import { gunzip } from 'zlib'; -import { Mov } from '../avm/opcodes/memory.js'; +import { Opcode } from './serialization/instruction_serialization.js'; const AVM_MAGIC_SUFFIX = Buffer.from([ - Mov.opcode, // opcode + Opcode.MOV_16, // opcode 0x00, // indirect - ...Buffer.from('000018ca', 'hex'), // srcOffset - ...Buffer.from('000018ca', 'hex'), // dstOffset + ...Buffer.from('18ca', 'hex'), // srcOffset + ...Buffer.from('18ca', 'hex'), // dstOffset ]); export function markBytecodeAsAvm(bytecode: Buffer): Buffer { diff --git a/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts b/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts index 10c92d9588c..3360317c3d6 100644 --- a/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/arithmetic.test.ts @@ -1,6 +1,7 @@ import { type AvmContext } from '../avm_context.js'; import { Field, TypeTag, Uint8, Uint16, Uint32, Uint64, Uint128 } from '../avm_memory_types.js'; import { initContext } from '../fixtures/index.js'; +import { Opcode } from '../serialization/instruction_serialization.js'; import { Add, Div, FieldDiv, Mul, Sub } from './arithmetic.js'; describe('Arithmetic Instructions', () => { @@ -13,22 +14,22 @@ describe('Arithmetic Instructions', () => { describe('Add', () => { it('Should (de)serialize correctly', () => { const buf = Buffer.from([ - Add.opcode, // opcode + Opcode.ADD_16, // opcode 0x01, // indirect TypeTag.FIELD, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Add( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.FIELD, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.ADD_16, Add.wireFormat16); - expect(Add.deserialize(buf)).toEqual(inst); + expect(Add.as(Add.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -77,22 +78,22 @@ describe('Arithmetic Instructions', () => { describe('Sub', () => { it('Should (de)serialize correctly', () => { const buf = Buffer.from([ - Sub.opcode, // opcode + Opcode.SUB_16, // opcode 0x01, // indirect TypeTag.FIELD, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Sub( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.FIELD, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.SUB_16, Sub.wireFormat16); - expect(Sub.deserialize(buf)).toEqual(inst); + expect(Sub.as(Sub.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -147,22 +148,22 @@ describe('Arithmetic Instructions', () => { describe('Mul', () => { it('Should (de)serialize correctly', () => { const buf = Buffer.from([ - Mul.opcode, // opcode + Opcode.MUL_16, // opcode 0x01, // indirect TypeTag.FIELD, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Mul( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.FIELD, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.MUL_16, Mul.wireFormat16); - expect(Mul.deserialize(buf)).toEqual(inst); + expect(Mul.as(Mul.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -212,22 +213,22 @@ describe('Arithmetic Instructions', () => { describe('Div', () => { it('Should (de)serialize correctly', () => { const buf = Buffer.from([ - Div.opcode, // opcode + Opcode.DIV_16, // opcode 0x01, // indirect TypeTag.FIELD, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Div( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.FIELD, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.DIV_16, Div.wireFormat16); - expect(Div.deserialize(buf)).toEqual(inst); + expect(Div.as(Div.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -256,20 +257,22 @@ describe('Arithmetic Instructions', () => { describe('FDiv', () => { it('Should (de)serialize correctly', () => { const buf = Buffer.from([ - FieldDiv.opcode, // opcode + Opcode.FDIV_16, // opcode 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + TypeTag.FIELD, // tag + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new FieldDiv( /*indirect=*/ 0x01, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*tag=*/ TypeTag.FIELD, + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.FDIV_16, FieldDiv.wireFormat16); - expect(FieldDiv.deserialize(buf)).toEqual(inst); + expect(FieldDiv.as(FieldDiv.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -280,7 +283,7 @@ describe('Arithmetic Instructions', () => { context.machineState.memory.set(0, a); context.machineState.memory.set(1, b); - await new Div( + await new FieldDiv( /*indirect=*/ 0, /*inTag=*/ TypeTag.FIELD, /*aOffset=*/ 0, diff --git a/yarn-project/simulator/src/avm/opcodes/arithmetic.ts b/yarn-project/simulator/src/avm/opcodes/arithmetic.ts index d918fbbd15c..acffa20c85d 100644 --- a/yarn-project/simulator/src/avm/opcodes/arithmetic.ts +++ b/yarn-project/simulator/src/avm/opcodes/arithmetic.ts @@ -1,8 +1,7 @@ import type { AvmContext } from '../avm_context.js'; -import { type Field, type MemoryValue, TypeTag } from '../avm_memory_types.js'; -import { Opcode, OperandType } from '../serialization/instruction_serialization.js'; +import { type Field, type MemoryValue } from '../avm_memory_types.js'; +import { Opcode } from '../serialization/instruction_serialization.js'; import { Addressing } from './addressing_mode.js'; -import { Instruction } from './instruction.js'; import { ThreeOperandInstruction } from './instruction_impl.js'; export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInstruction { @@ -32,7 +31,7 @@ export abstract class ThreeOperandArithmeticInstruction extends ThreeOperandInst export class Add extends ThreeOperandArithmeticInstruction { static readonly type: string = 'ADD'; - static readonly opcode = Opcode.ADD; + static readonly opcode = Opcode.ADD_8; // FIXME: needed for gas. protected compute(a: MemoryValue, b: MemoryValue): MemoryValue { return a.add(b); @@ -41,7 +40,7 @@ export class Add extends ThreeOperandArithmeticInstruction { export class Sub extends ThreeOperandArithmeticInstruction { static readonly type: string = 'SUB'; - static readonly opcode = Opcode.SUB; + static readonly opcode = Opcode.SUB_8; // FIXME: needed for gas. protected compute(a: MemoryValue, b: MemoryValue): MemoryValue { return a.sub(b); @@ -50,7 +49,7 @@ export class Sub extends ThreeOperandArithmeticInstruction { export class Mul extends ThreeOperandArithmeticInstruction { static type: string = 'MUL'; - static readonly opcode = Opcode.MUL; + static readonly opcode = Opcode.MUL_8; // FIXME: needed for gas. protected compute(a: MemoryValue, b: MemoryValue): MemoryValue { return a.mul(b); @@ -59,48 +58,20 @@ export class Mul extends ThreeOperandArithmeticInstruction { export class Div extends ThreeOperandArithmeticInstruction { static type: string = 'DIV'; - static readonly opcode = Opcode.DIV; + static readonly opcode = Opcode.DIV_8; // FIXME: needed for gas. protected compute(a: MemoryValue, b: MemoryValue): MemoryValue { return a.div(b); } } -export class FieldDiv extends Instruction { +// TODO: This class now temporarily has a tag, until all tags are removed. +export class FieldDiv extends ThreeOperandArithmeticInstruction { static type: string = 'FDIV'; - static readonly opcode = Opcode.FDIV; - - // Informs (de)serialization. See Instruction.deserialize. - static readonly wireFormat: OperandType[] = [ - OperandType.UINT8, - OperandType.UINT8, - OperandType.UINT32, - OperandType.UINT32, - OperandType.UINT32, - ]; - - constructor(private indirect: number, private aOffset: number, private bOffset: number, private dstOffset: number) { - super(); - } - - public async execute(context: AvmContext): Promise { - const memoryOperations = { reads: 2, writes: 1, indirect: this.indirect }; - const memory = context.machineState.memory.track(this.type); - context.machineState.consumeGas(this.gasCost(memoryOperations)); - - const [aOffset, bOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve( - [this.aOffset, this.bOffset, this.dstOffset], - memory, - ); - memory.checkTags(TypeTag.FIELD, aOffset, bOffset); - - const a = memory.getAs(aOffset); - const b = memory.getAs(bOffset); + static readonly opcode = Opcode.FDIV_8; // FIXME: needed for gas. - const dest = a.fdiv(b); - memory.set(dstOffset, dest); - - memory.assert(memoryOperations); - context.machineState.incrementPc(); + protected compute(a: Field, b: Field): Field { + // return (a as Field).fdiv(b as Field); + return a.fdiv(b); } } diff --git a/yarn-project/simulator/src/avm/opcodes/bitwise.test.ts b/yarn-project/simulator/src/avm/opcodes/bitwise.test.ts index 2d8e5308cc6..ff6b355fa71 100644 --- a/yarn-project/simulator/src/avm/opcodes/bitwise.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/bitwise.test.ts @@ -1,6 +1,7 @@ import { type AvmContext } from '../avm_context.js'; import { TypeTag, Uint8, Uint16, Uint32 } from '../avm_memory_types.js'; import { initContext } from '../fixtures/index.js'; +import { Opcode } from '../serialization/instruction_serialization.js'; import { And, Not, Or, Shl, Shr, Xor } from './bitwise.js'; describe('Bitwise instructions', () => { @@ -13,22 +14,22 @@ describe('Bitwise instructions', () => { describe('AND', () => { it('Should deserialize correctly', () => { const buf = Buffer.from([ - And.opcode, // opcode + Opcode.AND_16, // opcode 0x01, // indirect TypeTag.UINT64, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new And( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT64, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.AND_16, And.wireFormat16); - expect(And.deserialize(buf)).toEqual(inst); + expect(And.as(And.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -52,22 +53,22 @@ describe('Bitwise instructions', () => { describe('OR', () => { it('Should deserialize correctly', () => { const buf = Buffer.from([ - Or.opcode, // opcode + Opcode.OR_16, // opcode 0x01, // indirect TypeTag.UINT64, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Or( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT64, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.OR_16, Or.wireFormat16); - expect(Or.deserialize(buf)).toEqual(inst); + expect(Or.as(Or.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -95,22 +96,22 @@ describe('Bitwise instructions', () => { describe('XOR', () => { it('Should deserialize correctly', () => { const buf = Buffer.from([ - Xor.opcode, // opcode + Opcode.XOR_16, // opcode 0x01, // indirect TypeTag.UINT64, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Xor( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT64, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.XOR_16, Xor.wireFormat16); - expect(Xor.deserialize(buf)).toEqual(inst); + expect(Xor.as(Xor.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -138,22 +139,22 @@ describe('Bitwise instructions', () => { describe('SHR', () => { it('Should deserialize correctly', () => { const buf = Buffer.from([ - Shr.opcode, // opcode + Opcode.SHR_16, // opcode 0x01, // indirect TypeTag.UINT64, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Shr( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT64, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.SHR_16, Shr.wireFormat16); - expect(Shr.deserialize(buf)).toEqual(inst); + expect(Shr.as(Shr.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -240,22 +241,22 @@ describe('Bitwise instructions', () => { describe('SHL', () => { it('Should deserialize correctly', () => { const buf = Buffer.from([ - Shl.opcode, // opcode + Opcode.SHL_16, // opcode 0x01, // indirect TypeTag.UINT64, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Shl( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT64, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.SHL_16, Shl.wireFormat16); - expect(Shl.deserialize(buf)).toEqual(inst); + expect(Shl.as(Shl.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); diff --git a/yarn-project/simulator/src/avm/opcodes/bitwise.ts b/yarn-project/simulator/src/avm/opcodes/bitwise.ts index e43f36550b0..7ead46b1bee 100644 --- a/yarn-project/simulator/src/avm/opcodes/bitwise.ts +++ b/yarn-project/simulator/src/avm/opcodes/bitwise.ts @@ -34,7 +34,7 @@ abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction { export class And extends ThreeOperandBitwiseInstruction { static readonly type: string = 'AND'; - static readonly opcode = Opcode.AND; + static readonly opcode = Opcode.AND_8; // FIXME: needed for gas. protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue { return a.and(b); @@ -43,7 +43,7 @@ export class And extends ThreeOperandBitwiseInstruction { export class Or extends ThreeOperandBitwiseInstruction { static readonly type: string = 'OR'; - static readonly opcode = Opcode.OR; + static readonly opcode = Opcode.OR_8; // FIXME: needed for gas. protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue { return a.or(b); @@ -52,7 +52,7 @@ export class Or extends ThreeOperandBitwiseInstruction { export class Xor extends ThreeOperandBitwiseInstruction { static readonly type: string = 'XOR'; - static readonly opcode = Opcode.XOR; + static readonly opcode = Opcode.XOR_8; // FIXME: needed for gas. protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue { return a.xor(b); @@ -61,7 +61,7 @@ export class Xor extends ThreeOperandBitwiseInstruction { export class Shl extends ThreeOperandBitwiseInstruction { static readonly type: string = 'SHL'; - static readonly opcode = Opcode.SHL; + static readonly opcode = Opcode.SHL_8; // FIXME: needed for gas. protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue { return a.shl(b); @@ -74,7 +74,7 @@ export class Shl extends ThreeOperandBitwiseInstruction { export class Shr extends ThreeOperandBitwiseInstruction { static readonly type: string = 'SHR'; - static readonly opcode = Opcode.SHR; + static readonly opcode = Opcode.SHR_8; // FIXME: needed for gas. protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue { return a.shr(b); diff --git a/yarn-project/simulator/src/avm/opcodes/comparators.test.ts b/yarn-project/simulator/src/avm/opcodes/comparators.test.ts index c9ae2d31fa5..7695478c68d 100644 --- a/yarn-project/simulator/src/avm/opcodes/comparators.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/comparators.test.ts @@ -2,6 +2,7 @@ import { type AvmContext } from '../avm_context.js'; import { Field, TypeTag, Uint8, Uint16, Uint32 } from '../avm_memory_types.js'; import { TagCheckError } from '../errors.js'; import { initContext } from '../fixtures/index.js'; +import { Opcode } from '../serialization/instruction_serialization.js'; import { Eq, Lt, Lte } from './comparators.js'; describe('Comparators', () => { @@ -14,22 +15,22 @@ describe('Comparators', () => { describe('Eq', () => { it('Should deserialize correctly', () => { const buf = Buffer.from([ - Eq.opcode, // opcode + Opcode.EQ_16, // opcode 0x01, // indirect TypeTag.UINT64, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Eq( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT64, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.EQ_16, Eq.wireFormat16); - expect(Eq.deserialize(buf)).toEqual(inst); + expect(Eq.as(Eq.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -86,22 +87,22 @@ describe('Comparators', () => { describe('Lt', () => { it('Should deserialize correctly', () => { const buf = Buffer.from([ - Lt.opcode, // opcode + Opcode.LT_16, // opcode 0x01, // indirect TypeTag.UINT64, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Lt( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT64, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.LT_16, Lt.wireFormat16); - expect(Lt.deserialize(buf)).toEqual(inst); + expect(Lt.as(Lt.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -158,22 +159,22 @@ describe('Comparators', () => { describe('Lte', () => { it('Should deserialize correctly', () => { const buf = Buffer.from([ - Lte.opcode, // opcode + Opcode.LTE_16, // opcode 0x01, // indirect TypeTag.UINT64, // inTag - ...Buffer.from('12345678', 'hex'), // aOffset - ...Buffer.from('23456789', 'hex'), // bOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('1234', 'hex'), // aOffset + ...Buffer.from('2345', 'hex'), // bOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Lte( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT64, - /*aOffset=*/ 0x12345678, - /*bOffset=*/ 0x23456789, - /*dstOffset=*/ 0x3456789a, - ); + /*aOffset=*/ 0x1234, + /*bOffset=*/ 0x2345, + /*dstOffset=*/ 0x3456, + ).as(Opcode.LTE_16, Lte.wireFormat16); - expect(Lte.deserialize(buf)).toEqual(inst); + expect(Lte.as(Lte.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); diff --git a/yarn-project/simulator/src/avm/opcodes/comparators.ts b/yarn-project/simulator/src/avm/opcodes/comparators.ts index c3e90da54c3..be0b5c69c09 100644 --- a/yarn-project/simulator/src/avm/opcodes/comparators.ts +++ b/yarn-project/simulator/src/avm/opcodes/comparators.ts @@ -31,7 +31,7 @@ abstract class ComparatorInstruction extends ThreeOperandInstruction { export class Eq extends ComparatorInstruction { static readonly type: string = 'EQ'; - static readonly opcode = Opcode.EQ; + static readonly opcode = Opcode.EQ_8; // FIXME: needed for gas. protected compare(a: MemoryValue, b: MemoryValue): boolean { return a.equals(b); @@ -40,7 +40,7 @@ export class Eq extends ComparatorInstruction { export class Lt extends ComparatorInstruction { static readonly type: string = 'LT'; - static readonly opcode = Opcode.LT; + static readonly opcode = Opcode.LT_8; // FIXME: needed for gas. protected compare(a: MemoryValue, b: MemoryValue): boolean { return a.lt(b); @@ -49,7 +49,7 @@ export class Lt extends ComparatorInstruction { export class Lte extends ComparatorInstruction { static readonly type: string = 'LTE'; - static readonly opcode = Opcode.LTE; + static readonly opcode = Opcode.LTE_8; // FIXME: needed for gas. protected compare(a: MemoryValue, b: MemoryValue): boolean { return a.lt(b) || a.equals(b); diff --git a/yarn-project/simulator/src/avm/opcodes/control_flow.test.ts b/yarn-project/simulator/src/avm/opcodes/control_flow.test.ts index abd6ea2958f..6c4996a488e 100644 --- a/yarn-project/simulator/src/avm/opcodes/control_flow.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/control_flow.test.ts @@ -15,9 +15,9 @@ describe('Control Flow Opcodes', () => { it('Should (de)serialize correctly', () => { const buf = Buffer.from([ Jump.opcode, // opcode - ...Buffer.from('12345678', 'hex'), // loc + ...Buffer.from('1234', 'hex'), // loc ]); - const inst = new Jump(/*loc=*/ 0x12345678); + const inst = new Jump(/*loc=*/ 0x1234); expect(Jump.deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); @@ -39,10 +39,10 @@ describe('Control Flow Opcodes', () => { const buf = Buffer.from([ JumpI.opcode, // opcode 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // loc - ...Buffer.from('a2345678', 'hex'), // condOffset + ...Buffer.from('1234', 'hex'), // loc + ...Buffer.from('a234', 'hex'), // condOffset ]); - const inst = new JumpI(/*indirect=*/ 1, /*loc=*/ 0x12345678, /*condOffset=*/ 0xa2345678); + const inst = new JumpI(/*indirect=*/ 1, /*loc=*/ 0x1234, /*condOffset=*/ 0xa234); expect(JumpI.deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); diff --git a/yarn-project/simulator/src/avm/opcodes/control_flow.ts b/yarn-project/simulator/src/avm/opcodes/control_flow.ts index 635430d6b83..e601bb3ad1a 100644 --- a/yarn-project/simulator/src/avm/opcodes/control_flow.ts +++ b/yarn-project/simulator/src/avm/opcodes/control_flow.ts @@ -7,9 +7,9 @@ import { Instruction } from './instruction.js'; export class Jump extends Instruction { static type: string = 'JUMP'; - static readonly opcode: Opcode = Opcode.JUMP; + static readonly opcode: Opcode = Opcode.JUMP_16; // Informs (de)serialization. See Instruction.deserialize. - static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT32]; + static readonly wireFormat: OperandType[] = [OperandType.UINT8, OperandType.UINT16]; constructor(private jumpOffset: number) { super(); @@ -26,14 +26,14 @@ export class Jump extends Instruction { export class JumpI extends Instruction { static type: string = 'JUMPI'; - static readonly opcode: Opcode = Opcode.JUMPI; + static readonly opcode: Opcode = Opcode.JUMPI_16; // Instruction wire format with opcode. static readonly wireFormat: OperandType[] = [ OperandType.UINT8, OperandType.UINT8, - OperandType.UINT32, - OperandType.UINT32, + OperandType.UINT16, + OperandType.UINT16, ]; constructor(private indirect: number, private loc: number, private condOffset: number) { diff --git a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts index 663b079a438..8cde0f61cb4 100644 --- a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts @@ -4,17 +4,18 @@ import { mock } from 'jest-mock-extended'; import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js'; import { type AvmContext } from '../avm_context.js'; -import { Field, Uint8, Uint32 } from '../avm_memory_types.js'; +import { Field, TypeTag, Uint8, Uint32 } from '../avm_memory_types.js'; import { markBytecodeAsAvm } from '../bytecode_utils.js'; import { adjustCalldataIndex, initContext, initHostStorage, initPersistableStateManager } from '../fixtures/index.js'; import { type HostStorage } from '../journal/host_storage.js'; import { type AvmPersistableStateManager } from '../journal/journal.js'; import { encodeToBytecode } from '../serialization/bytecode_serialization.js'; +import { Opcode } from '../serialization/instruction_serialization.js'; import { mockGetBytecode, mockTraceFork } from '../test_utils.js'; import { L2GasLeft } from './context_getters.js'; import { Call, Return, Revert, StaticCall } from './external_calls.js'; import { type Instruction } from './instruction.js'; -import { CalldataCopy } from './memory.js'; +import { CalldataCopy, Set } from './memory.js'; import { SStore } from './storage.js'; describe('External Calls', () => { @@ -83,12 +84,12 @@ describe('External Calls', () => { // const otherContextInstructionsL2GasCost = 780; // Includes the cost of the call itself const otherContextInstructionsBytecode = markBytecodeAsAvm( encodeToBytecode([ - new CalldataCopy( - /*indirect=*/ 0, - /*csOffset=*/ adjustCalldataIndex(0), - /*copySize=*/ argsSize, - /*dstOffset=*/ 0, + new Set(/*indirect=*/ 0, TypeTag.UINT32, adjustCalldataIndex(0), /*dstOffset=*/ 0).as( + Opcode.SET_8, + Set.wireFormat8, ), + new Set(/*indirect=*/ 0, TypeTag.UINT32, argsSize, /*dstOffset=*/ 1).as(Opcode.SET_8, Set.wireFormat8), + new CalldataCopy(/*indirect=*/ 0, /*csOffsetAddress=*/ 0, /*copySizeOffset=*/ 1, /*dstOffset=*/ 0), new SStore(/*indirect=*/ 0, /*srcOffset=*/ valueOffset, /*slotOffset=*/ slotOffset), new Return(/*indirect=*/ 0, /*retOffset=*/ 0, /*size=*/ 2), ]), diff --git a/yarn-project/simulator/src/avm/opcodes/instruction.ts b/yarn-project/simulator/src/avm/opcodes/instruction.ts index 3eb22810bbd..ae211a73acf 100644 --- a/yarn-project/simulator/src/avm/opcodes/instruction.ts +++ b/yarn-project/simulator/src/avm/opcodes/instruction.ts @@ -4,11 +4,11 @@ import type { AvmContext } from '../avm_context.js'; import { getBaseGasCost, getDynamicGasCost, mulGas, sumGas } from '../avm_gas.js'; import { type MemoryOperations } from '../avm_memory_types.js'; import { type BufferCursor } from '../serialization/buffer_cursor.js'; -import { Opcode, type OperandType, deserialize, serialize } from '../serialization/instruction_serialization.js'; +import { type Serializable } from '../serialization/bytecode_serialization.js'; +import { Opcode, type OperandType, deserialize, serializeAs } from '../serialization/instruction_serialization.js'; type InstructionConstructor = { new (...args: any[]): Instruction; - wireFormat?: OperandType[]; }; /** @@ -37,29 +37,51 @@ export abstract class Instruction { return instructionStr; } + // Default deserialization which uses Class.opcode and Class.wireFormat. + public static deserialize( + this: InstructionConstructor & { wireFormat: OperandType[]; as: any }, + buf: BufferCursor | Buffer, + ): Instruction { + return this.as(this.wireFormat).deserialize(buf); + } + + // Default serialization which uses Class.opcode and Class.wireFormat. + public serialize(): Buffer { + const klass = this.constructor as any; + assert(klass.opcode !== undefined && klass.opcode !== null); + assert(klass.wireFormat !== undefined && klass.wireFormat !== null); + return this.as(klass.opcode, klass.wireFormat).serialize(); + } + /** - * Serialize the instruction to a Buffer according to its wire format specified in its subclass. - * If you want to use this, your subclass should specify a {@code static wireFormat: OperandType[]}. - * @param this - The instruction to serialize. - * @returns The serialized instruction. + * Returns a new instruction instance that can be serialized with the given opcode and wire format. + * @param opcode The opcode of the instruction. + * @param wireFormat The wire format of the instruction. + * @returns The new instruction instance. */ - public serialize(this: any): Buffer { - assert(!!this.constructor.wireFormat, 'wireFormat must be defined on the class'); - return serialize(this.constructor.wireFormat, this); + public as(opcode: Opcode, wireFormat: OperandType[]): Instruction & Serializable { + return Object.defineProperty(this, 'serialize', { + value: (): Buffer => { + return serializeAs(wireFormat, opcode, this); + }, + enumerable: false, + }); } /** - * Deserializes a subclass of Instruction from a Buffer. - * If you want to use this, your subclass should specify a {@code static wireFormat: OperandType[]}. - * @param this Class object to deserialize to. - * @param buf Buffer to read from. - * @returns Constructed instance of Class. + * Returns a new instruction class that can be deserialized with the given opcode and wire format. + * @param opcode The opcode of the instruction. + * @param wireFormat The wire format of the instruction. + * @returns The new instruction class. */ - public static deserialize(this: InstructionConstructor, buf: BufferCursor | Buffer): Instruction { - assert(!!this.wireFormat, 'wireFormat must be defined on the instruction class'); - const res = deserialize(buf, this.wireFormat); - const args = res.slice(1); // Remove opcode. - return new this(...args); + public static as(this: InstructionConstructor, wireFormat: OperandType[]) { + return Object.assign(this, { + deserialize: (buf: BufferCursor | Buffer): Instruction => { + const res = deserialize(buf, wireFormat); + const args = res.slice(1); // Remove opcode. + return new this(...args); + }, + }); } /** diff --git a/yarn-project/simulator/src/avm/opcodes/instruction_impl.ts b/yarn-project/simulator/src/avm/opcodes/instruction_impl.ts index f5797d526f8..01166d42314 100644 --- a/yarn-project/simulator/src/avm/opcodes/instruction_impl.ts +++ b/yarn-project/simulator/src/avm/opcodes/instruction_impl.ts @@ -14,13 +14,21 @@ export const TwoOperandWireFormat = [ ]; /** Wire format that informs deserialization for instructions with three operands. */ -export const ThreeOperandWireFormat = [ +export const ThreeOperandWireFormat8 = [ + OperandType.UINT8, + OperandType.UINT8, + OperandType.UINT8, OperandType.UINT8, OperandType.UINT8, OperandType.UINT8, - OperandType.UINT32, - OperandType.UINT32, - OperandType.UINT32, +]; +export const ThreeOperandWireFormat16 = [ + OperandType.UINT8, + OperandType.UINT8, + OperandType.UINT8, + OperandType.UINT16, + OperandType.UINT16, + OperandType.UINT16, ]; /** @@ -46,8 +54,8 @@ export abstract class TwoOperandInstruction extends Instruction { * indirect, inTag, and three UINT32s. */ export abstract class ThreeOperandInstruction extends Instruction { - // Informs (de)serialization. See Instruction.deserialize. - static readonly wireFormat: OperandType[] = ThreeOperandWireFormat; + static readonly wireFormat8: OperandType[] = ThreeOperandWireFormat8; + static readonly wireFormat16: OperandType[] = ThreeOperandWireFormat16; constructor( protected indirect: number, diff --git a/yarn-project/simulator/src/avm/opcodes/memory.test.ts b/yarn-project/simulator/src/avm/opcodes/memory.test.ts index d2b4eab29c2..99967748062 100644 --- a/yarn-project/simulator/src/avm/opcodes/memory.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/memory.test.ts @@ -2,8 +2,8 @@ import { Fr } from '@aztec/foundation/fields'; import { type AvmContext } from '../avm_context.js'; import { Field, TypeTag, Uint8, Uint16, Uint32, Uint64, Uint128 } from '../avm_memory_types.js'; -import { InstructionExecutionError } from '../errors.js'; import { adjustCalldataIndex, initContext, initExecutionEnvironment } from '../fixtures/index.js'; +import { Opcode } from '../serialization/instruction_serialization.js'; import { Addressing, AddressingMode } from './addressing_mode.js'; import { CMov, CalldataCopy, Cast, Mov, Set } from './memory.js'; @@ -17,86 +17,111 @@ describe('Memory instructions', () => { describe('SET', () => { it('Should (de)serialize correctly [tag=u8]', () => { const buf = Buffer.from([ - Set.opcode, // opcode + Opcode.SET_8, // opcode 0x01, // indirect TypeTag.UINT8, // inTag ...Buffer.from('12', 'hex'), - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('56', 'hex'), // dstOffset ]); - const inst = new Set(/*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT8, /*value=*/ 0x12, /*dstOffset=*/ 0x3456789a); + const inst = new Set(/*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT8, /*value=*/ 0x12, /*dstOffset=*/ 0x56).as( + Opcode.SET_8, + Set.wireFormat8, + ); - expect(Set.deserialize(buf)).toEqual(inst); + expect(Set.as(Set.wireFormat8).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); it('Should (de)serialize correctly [tag=u16]', () => { const buf = Buffer.from([ - Set.opcode, // opcode + Opcode.SET_16, // opcode 0x01, // indirect TypeTag.UINT16, // inTag ...Buffer.from('1234', 'hex'), - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); - const inst = new Set(/*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT16, /*value=*/ 0x1234, /*dstOffset=*/ 0x3456789a); + const inst = new Set(/*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT16, /*value=*/ 0x1234, /*dstOffset=*/ 0x3456).as( + Opcode.SET_16, + Set.wireFormat16, + ); - expect(Set.deserialize(buf)).toEqual(inst); + expect(Set.as(Set.wireFormat16).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); it('Should (de)serialize correctly [tag=u32]', () => { const buf = Buffer.from([ - Set.opcode, // opcode + Opcode.SET_32, // opcode 0x01, // indirect TypeTag.UINT32, // inTag ...Buffer.from('12345678', 'hex'), - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Set( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT32, /*value=*/ 0x12345678, - /*dstOffset=*/ 0x3456789a, - ); + /*dstOffset=*/ 0x3456, + ).as(Opcode.SET_32, Set.wireFormat32); - expect(Set.deserialize(buf)).toEqual(inst); + expect(Set.as(Set.wireFormat32).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); it('Should (de)serialize correctly [tag=u64]', () => { const buf = Buffer.from([ - Set.opcode, // opcode + Opcode.SET_64, // opcode 0x01, // indirect TypeTag.UINT64, // inTag ...Buffer.from('1234567812345678', 'hex'), - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('34567', 'hex'), // dstOffset ]); const inst = new Set( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT64, /*value=*/ 0x1234567812345678n, - /*dstOffset=*/ 0x3456789a, - ); + /*dstOffset=*/ 0x3456, + ).as(Opcode.SET_64, Set.wireFormat64); - expect(Set.deserialize(buf)).toEqual(inst); + expect(Set.as(Set.wireFormat64).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); it('Should (de)serialize correctly [tag=u128]', () => { const buf = Buffer.from([ - Set.opcode, // opcode + Opcode.SET_128, // opcode 0x01, // indirect TypeTag.UINT128, // inTag ...Buffer.from('12345678123456781234567812345678', 'hex'), // const (will be 128 bit) - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('3456', 'hex'), // dstOffset ]); const inst = new Set( /*indirect=*/ 0x01, /*inTag=*/ TypeTag.UINT128, /*value=*/ 0x12345678123456781234567812345678n, - /*dstOffset=*/ 0x3456789a, - ); + /*dstOffset=*/ 0x3456, + ).as(Opcode.SET_128, Set.wireFormat128); - expect(Set.deserialize(buf)).toEqual(inst); + expect(Set.as(Set.wireFormat128).deserialize(buf)).toEqual(inst); + expect(inst.serialize()).toEqual(buf); + }); + + it('Should (de)serialize correctly [tag=ff]', () => { + const buf = Buffer.from([ + Opcode.SET_FF, // opcode + 0x01, // indirect + TypeTag.UINT128, // inTag + ...Buffer.from('1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', 'hex'), // const (will be 32 bytes) + ...Buffer.from('3456', 'hex'), // dstOffset + ]); + const inst = new Set( + /*indirect=*/ 0x01, + /*inTag=*/ TypeTag.UINT128, + /*value=*/ 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdefn, + /*dstOffset=*/ 0x3456, + ).as(Opcode.SET_FF, Set.wireFormatFF); + + expect(Set.as(Set.wireFormatFF).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -131,14 +156,6 @@ describe('Memory instructions', () => { expect(actual).toEqual(new Uint16(0x5678)); expect(tag).toEqual(TypeTag.UINT16); }); - - it('should throw if tag is FIELD, UNINITIALIZED, INVALID', async () => { - for (const tag of [TypeTag.FIELD, TypeTag.UNINITIALIZED, TypeTag.INVALID]) { - await expect( - async () => await new Set(/*indirect=*/ 0, /*inTag=*/ tag, /*value=*/ 1234n, /*offset=*/ 1).execute(context), - ).rejects.toThrow(InstructionExecutionError); - } - }); }); describe('CAST', () => { @@ -302,12 +319,15 @@ describe('Memory instructions', () => { const buf = Buffer.from([ Mov.opcode, // opcode 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // srcOffset - ...Buffer.from('3456789a', 'hex'), // dstOffset + ...Buffer.from('12', 'hex'), // srcOffset + ...Buffer.from('34', 'hex'), // dstOffset ]); - const inst = new Mov(/*indirect=*/ 0x01, /*srcOffset=*/ 0x12345678, /*dstOffset=*/ 0x3456789a); + const inst = new Mov(/*indirect=*/ 0x01, /*srcOffset=*/ 0x12, /*dstOffset=*/ 0x34).as( + Opcode.MOV_8, + Mov.wireFormat8, + ); - expect(Mov.deserialize(buf)).toEqual(inst); + expect(Mov.as(Mov.wireFormat8).deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); }); @@ -432,14 +452,14 @@ describe('Memory instructions', () => { const buf = Buffer.from([ CalldataCopy.opcode, // opcode 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // cdOffset - ...Buffer.from('23456789', 'hex'), // copysize + ...Buffer.from('12345678', 'hex'), // cdOffsetAddress + ...Buffer.from('23456789', 'hex'), // copysizeOffset ...Buffer.from('3456789a', 'hex'), // dstOffset ]); const inst = new CalldataCopy( /*indirect=*/ 0x01, - /*cdOffset=*/ 0x12345678, - /*copysize=*/ 0x23456789, + /*cdOffsetAddress=*/ 0x12345678, + /*copysizeOffset=*/ 0x23456789, /*dstOffset=*/ 0x3456789a, ); @@ -450,30 +470,23 @@ describe('Memory instructions', () => { it('Writes nothing if size is 0', async () => { const calldata = [new Fr(1n), new Fr(2n), new Fr(3n)]; context = initContext({ env: initExecutionEnvironment({ calldata }) }); - context.machineState.memory.set(0, new Uint16(12)); // Some previous data to be overwritten + context.machineState.memory.set(0, new Uint32(adjustCalldataIndex(0))); // cdoffset + context.machineState.memory.set(1, new Uint32(0)); // size + context.machineState.memory.set(3, new Uint16(12)); // not overwritten - await new CalldataCopy( - /*indirect=*/ 0, - /*cdOffset=*/ adjustCalldataIndex(0), - /*copySize=*/ 0, - /*dstOffset=*/ 0, - ).execute(context); + await new CalldataCopy(/*indirect=*/ 0, /*cdOffset=*/ 0, /*copySize=*/ 1, /*dstOffset=*/ 0).execute(context); - const actual = context.machineState.memory.get(0); + const actual = context.machineState.memory.get(3); expect(actual).toEqual(new Uint16(12)); }); it('Copies all calldata', async () => { const calldata = [new Fr(1n), new Fr(2n), new Fr(3n)]; context = initContext({ env: initExecutionEnvironment({ calldata }) }); - context.machineState.memory.set(0, new Uint16(12)); // Some previous data to be overwritten + context.machineState.memory.set(0, new Uint32(adjustCalldataIndex(0))); // cdoffset + context.machineState.memory.set(1, new Uint32(3)); // size - await new CalldataCopy( - /*indirect=*/ 0, - /*cdOffset=*/ adjustCalldataIndex(0), - /*copySize=*/ 3, - /*dstOffset=*/ 0, - ).execute(context); + await new CalldataCopy(/*indirect=*/ 0, /*cdOffset=*/ 0, /*copySize=*/ 1, /*dstOffset=*/ 0).execute(context); const actual = context.machineState.memory.getSlice(/*offset=*/ 0, /*size=*/ 3); expect(actual).toEqual([new Field(1), new Field(2), new Field(3)]); @@ -482,14 +495,10 @@ describe('Memory instructions', () => { it('Copies slice of calldata', async () => { const calldata = [new Fr(1n), new Fr(2n), new Fr(3n)]; context = initContext({ env: initExecutionEnvironment({ calldata }) }); - context.machineState.memory.set(0, new Uint16(12)); // Some previous data to be overwritten - - await new CalldataCopy( - /*indirect=*/ 0, - /*cdOffset=*/ adjustCalldataIndex(1), - /*copySize=*/ 2, - /*dstOffset=*/ 0, - ).execute(context); + context.machineState.memory.set(0, new Uint32(adjustCalldataIndex(1))); // cdoffset + context.machineState.memory.set(1, new Uint32(2)); // size + + await new CalldataCopy(/*indirect=*/ 0, /*cdOffset=*/ 0, /*copySize=*/ 1, /*dstOffset=*/ 0).execute(context); const actual = context.machineState.memory.getSlice(/*offset=*/ 0, /*size=*/ 2); expect(actual).toEqual([new Field(2), new Field(3)]); diff --git a/yarn-project/simulator/src/avm/opcodes/memory.ts b/yarn-project/simulator/src/avm/opcodes/memory.ts index 3c37672c028..66a04494af2 100644 --- a/yarn-project/simulator/src/avm/opcodes/memory.ts +++ b/yarn-project/simulator/src/avm/opcodes/memory.ts @@ -1,39 +1,57 @@ import type { AvmContext } from '../avm_context.js'; -import { Field, TaggedMemory, TypeTag } from '../avm_memory_types.js'; -import { InstructionExecutionError } from '../errors.js'; -import { BufferCursor } from '../serialization/buffer_cursor.js'; -import { Opcode, OperandType, deserialize, serialize } from '../serialization/instruction_serialization.js'; +import { Field, TaggedMemory } from '../avm_memory_types.js'; +import { Opcode, OperandType } from '../serialization/instruction_serialization.js'; import { Addressing } from './addressing_mode.js'; import { Instruction } from './instruction.js'; import { TwoOperandInstruction } from './instruction_impl.js'; -const TAG_TO_OPERAND_TYPE = new Map([ - [TypeTag.UINT8, OperandType.UINT8], - [TypeTag.UINT16, OperandType.UINT16], - [TypeTag.UINT32, OperandType.UINT32], - [TypeTag.UINT64, OperandType.UINT64], - [TypeTag.UINT128, OperandType.UINT128], -]); - -function getOperandTypeFromInTag(inTag: number | bigint): OperandType { - inTag = inTag as number; - const tagOperandType = TAG_TO_OPERAND_TYPE.get(inTag); - if (tagOperandType === undefined) { - throw new Error(`Invalid tag ${inTag} for SET.`); - } - return tagOperandType; -} - export class Set extends Instruction { static readonly type: string = 'SET'; - static readonly opcode: Opcode = Opcode.SET; - - private static readonly wireFormatBeforeConst: OperandType[] = [ - OperandType.UINT8, - OperandType.UINT8, - OperandType.UINT8, + // Required for gas. + static readonly opcode: Opcode = Opcode.SET_8; + + public static readonly wireFormat8: OperandType[] = [ + OperandType.UINT8, // opcode + OperandType.UINT8, // indirect + OperandType.UINT8, // tag + OperandType.UINT8, // const (value) + OperandType.UINT8, // dstOffset + ]; + public static readonly wireFormat16: OperandType[] = [ + OperandType.UINT8, // opcode + OperandType.UINT8, // indirect + OperandType.UINT8, // tag + OperandType.UINT16, // const (value) + OperandType.UINT16, // dstOffset + ]; + public static readonly wireFormat32: OperandType[] = [ + OperandType.UINT8, // opcode + OperandType.UINT8, // indirect + OperandType.UINT8, // tag + OperandType.UINT32, // const (value) + OperandType.UINT16, // dstOffset + ]; + public static readonly wireFormat64: OperandType[] = [ + OperandType.UINT8, // opcode + OperandType.UINT8, // indirect + OperandType.UINT8, // tag + OperandType.UINT64, // const (value) + OperandType.UINT16, // dstOffset + ]; + public static readonly wireFormat128: OperandType[] = [ + OperandType.UINT8, // opcode + OperandType.UINT8, // indirect + OperandType.UINT8, // tag + OperandType.UINT128, // const (value) + OperandType.UINT16, // dstOffset + ]; + public static readonly wireFormatFF: OperandType[] = [ + OperandType.UINT8, // opcode + OperandType.UINT8, // indirect + OperandType.UINT8, // tag + OperandType.FF, // const (value) + OperandType.UINT16, // dstOffset ]; - private static readonly wireFormatAfterConst: OperandType[] = [OperandType.UINT32]; constructor( private indirect: number, @@ -44,42 +62,13 @@ export class Set extends Instruction { super(); } - /** We need to use a custom serialize function because of the variable length of the value. */ - public override serialize(): Buffer { - const format: OperandType[] = [ - ...Set.wireFormatBeforeConst, - getOperandTypeFromInTag(this.inTag), - ...Set.wireFormatAfterConst, - ]; - return serialize(format, this); - } - - /** We need to use a custom deserialize function because of the variable length of the value. */ - public static override deserialize(this: typeof Set, buf: BufferCursor | Buffer): Set { - if (buf instanceof Buffer) { - buf = new BufferCursor(buf); - } - const beforeConst = deserialize(buf, Set.wireFormatBeforeConst); - const tag = beforeConst[beforeConst.length - 1]; - const val = deserialize(buf, [getOperandTypeFromInTag(tag)]); - const afterConst = deserialize(buf, Set.wireFormatAfterConst); - const res = [...beforeConst, ...val, ...afterConst]; - const args = res.slice(1) as ConstructorParameters; // Remove opcode. - return new this(...args); - } - public async execute(context: AvmContext): Promise { const memoryOperations = { writes: 1, indirect: this.indirect }; const memory = context.machineState.memory.track(this.type); context.machineState.consumeGas(this.gasCost(memoryOperations)); - // Per the YP, the tag cannot be a field. - if ([TypeTag.FIELD, TypeTag.UNINITIALIZED, TypeTag.INVALID].includes(this.inTag)) { - throw new InstructionExecutionError(`Invalid tag ${TypeTag[this.inTag]} for SET.`); - } const [dstOffset] = Addressing.fromWire(this.indirect).resolve([this.dstOffset], memory); - - const res = TaggedMemory.integralFromTag(this.value, this.inTag); + const res = TaggedMemory.buildFromTagTruncating(this.value, this.inTag); memory.set(dstOffset, res); memory.assert(memoryOperations); @@ -148,9 +137,7 @@ export class Cast extends TwoOperandInstruction { const [srcOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.aOffset, this.dstOffset], memory); const a = memory.get(srcOffset); - - const casted = - this.inTag == TypeTag.FIELD ? new Field(a.toBigInt()) : TaggedMemory.integralFromTag(a.toBigInt(), this.inTag); + const casted = TaggedMemory.buildFromTagTruncating(a.toBigInt(), this.inTag); memory.set(dstOffset, casted); @@ -161,13 +148,20 @@ export class Cast extends TwoOperandInstruction { export class Mov extends Instruction { static readonly type: string = 'MOV'; - static readonly opcode: Opcode = Opcode.MOV; - // Informs (de)serialization. See Instruction.deserialize. - static readonly wireFormat: OperandType[] = [ + // FIXME: This is needed for gas. + static readonly opcode: Opcode = Opcode.MOV_8; + + static readonly wireFormat8: OperandType[] = [ OperandType.UINT8, OperandType.UINT8, - OperandType.UINT32, - OperandType.UINT32, + OperandType.UINT8, + OperandType.UINT8, + ]; + static readonly wireFormat16: OperandType[] = [ + OperandType.UINT8, + OperandType.UINT8, + OperandType.UINT16, + OperandType.UINT16, ]; constructor(private indirect: number, private srcOffset: number, private dstOffset: number) { @@ -202,21 +196,29 @@ export class CalldataCopy extends Instruction { OperandType.UINT32, ]; - constructor(private indirect: number, private cdOffset: number, private copySize: number, private dstOffset: number) { + constructor( + private indirect: number, + private cdStartOffset: number, + private copySizeOffset: number, + private dstOffset: number, + ) { super(); } public async execute(context: AvmContext): Promise { - const memoryOperations = { writes: this.copySize, indirect: this.indirect }; const memory = context.machineState.memory.track(this.type); - context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: this.copySize })); - // We don't need to check tags here because: (1) the calldata is NOT in memory, and (2) we are the ones writing to destination. - const [cdOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve([this.cdOffset, this.dstOffset], memory); + const [cdStartOffset, copySizeOffset, dstOffset] = Addressing.fromWire(this.indirect).resolve( + [this.cdStartOffset, this.copySizeOffset, this.dstOffset], + memory, + ); + + const cdStart = memory.get(cdStartOffset).toNumber(); + const copySize = memory.get(copySizeOffset).toNumber(); + const memoryOperations = { reads: 2, writes: copySize, indirect: this.indirect }; + context.machineState.consumeGas(this.gasCost({ ...memoryOperations, dynMultiplier: copySize })); - const transformedData = context.environment.calldata - .slice(cdOffset, cdOffset + this.copySize) - .map(f => new Field(f)); + const transformedData = context.environment.calldata.slice(cdStart, cdStart + copySize).map(f => new Field(f)); memory.setSlice(dstOffset, transformedData); diff --git a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts index 4dd26fb13dd..10354bcc410 100644 --- a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts +++ b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts @@ -3,7 +3,7 @@ import { strict as assert } from 'assert'; import { Add, Address, Call, StaticCall, Sub } from '../opcodes/index.js'; import { type BufferCursor } from './buffer_cursor.js'; import { type InstructionSet, decodeFromBytecode, encodeToBytecode } from './bytecode_serialization.js'; -import { type Opcode } from './instruction_serialization.js'; +import { Opcode } from './instruction_serialization.js'; class InstA { constructor(private n: number) {} @@ -48,8 +48,8 @@ class InstB { describe('Bytecode Serialization', () => { it('Should deserialize using instruction set', () => { const instructionSet: InstructionSet = new Map([ - [InstA.opcode, InstA], - [InstB.opcode, InstB], + [InstA.opcode, InstA.deserialize], + [InstB.opcode, InstB.deserialize], ]); const a = new InstA(0x1234); const b = new InstB(0x5678n); @@ -72,8 +72,14 @@ describe('Bytecode Serialization', () => { it('Should deserialize real instructions', () => { const instructions = [ - new Add(/*indirect=*/ 0, /*inTag=*/ 0, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2), - new Sub(/*indirect=*/ 0, /*inTag=*/ 0, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2), + new Add(/*indirect=*/ 0, /*inTag=*/ 0, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2).as( + Opcode.ADD_8, + Add.wireFormat8, + ), + new Sub(/*indirect=*/ 0, /*inTag=*/ 0, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2).as( + Opcode.SUB_8, + Sub.wireFormat8, + ), new Address(/*indirect=*/ 0, /*dstOffset=*/ 1), new Call( /*indirect=*/ 0x01, @@ -107,8 +113,14 @@ describe('Bytecode Serialization', () => { it('Should serialize real instructions', () => { const instructions = [ - new Add(/*indirect=*/ 0, /*inTag=*/ 0, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2), - new Sub(/*indirect=*/ 0, /*inTag=*/ 0, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2), + new Add(/*indirect=*/ 0, /*inTag=*/ 0, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2).as( + Opcode.ADD_8, + Add.wireFormat8, + ), + new Sub(/*indirect=*/ 0, /*inTag=*/ 0, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2).as( + Opcode.SUB_8, + Sub.wireFormat8, + ), new Address(/*indirect=*/ 0, /*dstOffset=*/ 1), new Call( /*indirect=*/ 0x01, diff --git a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts index 034588db6e3..3b435b0386a 100644 --- a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts @@ -2,7 +2,7 @@ import { PedersenCommitment } from '../opcodes/commitment.js'; import { DAGasLeft, L2GasLeft } from '../opcodes/context_getters.js'; import { EcAdd } from '../opcodes/ec_add.js'; import { Keccak, KeccakF1600, Pedersen, Poseidon2, Sha256 } from '../opcodes/hashing.js'; -import type { Instruction } from '../opcodes/index.js'; +import { Instruction } from '../opcodes/index.js'; import { Add, Address, @@ -59,105 +59,122 @@ import { MultiScalarMul } from '../opcodes/multi_scalar_mul.js'; import { BufferCursor } from './buffer_cursor.js'; import { Opcode } from './instruction_serialization.js'; -interface DeserializableInstruction { - deserialize(buf: BufferCursor | Buffer): Instruction; - opcode: Opcode; +export type InstructionDeserializer = (buf: BufferCursor | Buffer) => Instruction; + +export interface Serializable { + serialize(): Buffer; +} + +export interface Deserializable { + deserialize: InstructionDeserializer; } -export type InstructionSet = Map; +export type InstructionSet = Map; // TODO(4359): This is a function so that Call and StaticCall can be lazily resolved. // This is a temporary solution until we solve the dependency cycle. const INSTRUCTION_SET = () => - new Map([ - [Add.opcode, Add], - [Sub.opcode, Sub], - [Mul.opcode, Mul], - [Div.opcode, Div], - [FieldDiv.opcode, FieldDiv], - [Eq.opcode, Eq], - [Lt.opcode, Lt], - [Lte.opcode, Lte], - [And.opcode, And], - [Or.opcode, Or], - [Xor.opcode, Xor], - [Not.opcode, Not], - [Shl.opcode, Shl], - [Shr.opcode, Shr], - [Cast.opcode, Cast], - [Address.opcode, Address], - [StorageAddress.opcode, StorageAddress], - [Sender.opcode, Sender], - [FunctionSelector.opcode, FunctionSelector], - [TransactionFee.opcode, TransactionFee], + new Map([ + [Opcode.ADD_8, Add.as(Add.wireFormat8).deserialize], + [Opcode.ADD_16, Add.as(Add.wireFormat16).deserialize], + [Opcode.SUB_8, Sub.as(Sub.wireFormat8).deserialize], + [Opcode.SUB_16, Sub.as(Sub.wireFormat16).deserialize], + [Opcode.MUL_8, Mul.as(Mul.wireFormat8).deserialize], + [Opcode.MUL_16, Mul.as(Mul.wireFormat16).deserialize], + [Opcode.DIV_8, Div.as(Div.wireFormat8).deserialize], + [Opcode.DIV_16, Div.as(Div.wireFormat16).deserialize], + [Opcode.FDIV_8, FieldDiv.as(FieldDiv.wireFormat8).deserialize], + [Opcode.FDIV_16, FieldDiv.as(FieldDiv.wireFormat16).deserialize], + [Opcode.EQ_8, Eq.as(Eq.wireFormat8).deserialize], + [Opcode.EQ_16, Eq.as(Eq.wireFormat16).deserialize], + [Opcode.LT_8, Lt.as(Lt.wireFormat8).deserialize], + [Opcode.LT_16, Lt.as(Lt.wireFormat16).deserialize], + [Opcode.LTE_8, Lte.as(Lte.wireFormat8).deserialize], + [Opcode.LTE_16, Lte.as(Lte.wireFormat16).deserialize], + [Opcode.AND_8, And.as(And.wireFormat8).deserialize], + [Opcode.AND_16, And.as(And.wireFormat16).deserialize], + [Opcode.OR_8, Or.as(Or.wireFormat8).deserialize], + [Opcode.OR_16, Or.as(Or.wireFormat16).deserialize], + [Opcode.XOR_8, Xor.as(Xor.wireFormat8).deserialize], + [Opcode.XOR_16, Xor.as(Xor.wireFormat16).deserialize], + [Not.opcode, Instruction.deserialize.bind(Not)], + [Opcode.SHL_8, Shl.as(Shl.wireFormat8).deserialize], + [Opcode.SHL_16, Shl.as(Shl.wireFormat16).deserialize], + [Opcode.SHR_8, Shr.as(Shr.wireFormat8).deserialize], + [Opcode.SHR_16, Shr.as(Shr.wireFormat16).deserialize], + [Cast.opcode, Instruction.deserialize.bind(Cast)], + [Address.opcode, Instruction.deserialize.bind(Address)], + [StorageAddress.opcode, Instruction.deserialize.bind(StorageAddress)], + [Sender.opcode, Instruction.deserialize.bind(Sender)], + [FunctionSelector.opcode, Instruction.deserialize.bind(FunctionSelector)], + [TransactionFee.opcode, Instruction.deserialize.bind(TransactionFee)], // Execution Environment - Globals - [ChainId.opcode, ChainId], - [Version.opcode, Version], - [BlockNumber.opcode, BlockNumber], - [Timestamp.opcode, Timestamp], - //[Coinbase.opcode, Coinbase], - [FeePerL2Gas.opcode, FeePerL2Gas], - [FeePerDAGas.opcode, FeePerDAGas], - //[Blockl2gaslimit.opcode, Blockl2gaslimit], - //[Blockdagaslimit.opcode, Blockdagaslimit], + [ChainId.opcode, Instruction.deserialize.bind(ChainId)], + [Version.opcode, Instruction.deserialize.bind(Version)], + [BlockNumber.opcode, Instruction.deserialize.bind(BlockNumber)], + [Timestamp.opcode, Instruction.deserialize.bind(Timestamp)], + [FeePerL2Gas.opcode, Instruction.deserialize.bind(FeePerL2Gas)], + [FeePerDAGas.opcode, Instruction.deserialize.bind(FeePerDAGas)], // Execution Environment - Calldata - [CalldataCopy.opcode, CalldataCopy], + [CalldataCopy.opcode, Instruction.deserialize.bind(CalldataCopy)], // Machine State // Machine State - Gas - [L2GasLeft.opcode, L2GasLeft], - [DAGasLeft.opcode, DAGasLeft], + [L2GasLeft.opcode, Instruction.deserialize.bind(L2GasLeft)], + [DAGasLeft.opcode, Instruction.deserialize.bind(DAGasLeft)], // Machine State - Internal Control Flow - [Jump.opcode, Jump], - [JumpI.opcode, JumpI], - [InternalCall.opcode, InternalCall], - [InternalReturn.opcode, InternalReturn], - [Set.opcode, Set], - [Mov.opcode, Mov], - [CMov.opcode, CMov], + [Jump.opcode, Instruction.deserialize.bind(Jump)], + [JumpI.opcode, Instruction.deserialize.bind(JumpI)], + [InternalCall.opcode, Instruction.deserialize.bind(InternalCall)], + [InternalReturn.opcode, Instruction.deserialize.bind(InternalReturn)], + [Opcode.SET_8, Set.as(Set.wireFormat8).deserialize], + [Opcode.SET_16, Set.as(Set.wireFormat16).deserialize], + [Opcode.SET_32, Set.as(Set.wireFormat32).deserialize], + [Opcode.SET_64, Set.as(Set.wireFormat64).deserialize], + [Opcode.SET_128, Set.as(Set.wireFormat128).deserialize], + [Opcode.SET_FF, Set.as(Set.wireFormatFF).deserialize], + [Opcode.MOV_8, Mov.as(Mov.wireFormat8).deserialize], + [Opcode.MOV_16, Mov.as(Mov.wireFormat16).deserialize], + [CMov.opcode, Instruction.deserialize.bind(CMov)], // World State - [SLoad.opcode, SLoad], // Public Storage - [SStore.opcode, SStore], // Public Storage - [NoteHashExists.opcode, NoteHashExists], // Notes & Nullifiers - [EmitNoteHash.opcode, EmitNoteHash], // Notes & Nullifiers - [NullifierExists.opcode, NullifierExists], // Notes & Nullifiers - [EmitNullifier.opcode, EmitNullifier], // Notes & Nullifiers - [L1ToL2MessageExists.opcode, L1ToL2MessageExists], // Messages + [SLoad.opcode, Instruction.deserialize.bind(SLoad)], // Public Storage + [SStore.opcode, Instruction.deserialize.bind(SStore)], // Public Storage + [NoteHashExists.opcode, Instruction.deserialize.bind(NoteHashExists)], // Notes & Nullifiers + [EmitNoteHash.opcode, Instruction.deserialize.bind(EmitNoteHash)], // Notes & Nullifiers + [NullifierExists.opcode, Instruction.deserialize.bind(NullifierExists)], // Notes & Nullifiers + [EmitNullifier.opcode, Instruction.deserialize.bind(EmitNullifier)], // Notes & Nullifiers + [L1ToL2MessageExists.opcode, Instruction.deserialize.bind(L1ToL2MessageExists)], // Messages // Accrued Substate - [EmitUnencryptedLog.opcode, EmitUnencryptedLog], - [SendL2ToL1Message.opcode, SendL2ToL1Message], - [GetContractInstance.opcode, GetContractInstance], + [EmitUnencryptedLog.opcode, Instruction.deserialize.bind(EmitUnencryptedLog)], + [SendL2ToL1Message.opcode, Instruction.deserialize.bind(SendL2ToL1Message)], + [GetContractInstance.opcode, Instruction.deserialize.bind(GetContractInstance)], // Control Flow - Contract Calls - [Call.opcode, Call], - [StaticCall.opcode, StaticCall], - //[DelegateCall.opcode, DelegateCall], - [Return.opcode, Return], - [Revert.opcode, Revert], + [Call.opcode, Instruction.deserialize.bind(Call)], + [StaticCall.opcode, Instruction.deserialize.bind(StaticCall)], + //[DelegateCall.opcode, Instruction.deserialize.bind(DelegateCall)], + [Return.opcode, Instruction.deserialize.bind(Return)], + [Revert.opcode, Instruction.deserialize.bind(Revert)], // Misc - [DebugLog.opcode, DebugLog], + [DebugLog.opcode, Instruction.deserialize.bind(DebugLog)], // Gadgets - [EcAdd.opcode, EcAdd], - [Keccak.opcode, Keccak], - [Poseidon2.opcode, Poseidon2], - [Sha256.opcode, Sha256], - [Pedersen.opcode, Pedersen], - [MultiScalarMul.opcode, MultiScalarMul], - [PedersenCommitment.opcode, PedersenCommitment], + [EcAdd.opcode, Instruction.deserialize.bind(EcAdd)], + [Keccak.opcode, Instruction.deserialize.bind(Keccak)], + [Poseidon2.opcode, Instruction.deserialize.bind(Poseidon2)], + [Sha256.opcode, Instruction.deserialize.bind(Sha256)], + [Pedersen.opcode, Instruction.deserialize.bind(Pedersen)], + [MultiScalarMul.opcode, Instruction.deserialize.bind(MultiScalarMul)], + [PedersenCommitment.opcode, Instruction.deserialize.bind(PedersenCommitment)], // Conversions - [ToRadixLE.opcode, ToRadixLE], + [ToRadixLE.opcode, Instruction.deserialize.bind(ToRadixLE)], // Future Gadgets -- pending changes in noir // SHA256COMPRESSION, - [KeccakF1600.opcode, KeccakF1600], + [KeccakF1600.opcode, Instruction.deserialize.bind(KeccakF1600)], ]); -interface Serializable { - serialize(): Buffer; -} - /** * Serializes an array of instructions to bytecode. */ @@ -185,8 +202,8 @@ export function decodeFromBytecode( throw new Error(`Opcode ${Opcode[opcode]} (0x${opcode.toString(16)}) not implemented`); } - const instructionDeserializer: DeserializableInstruction = instructionDeserializerOrUndef; - const i: Instruction = instructionDeserializer.deserialize(cursor); + const instructionDeserializer: InstructionDeserializer = instructionDeserializerOrUndef; + const i: Instruction = instructionDeserializer(cursor); instructions.push(i); } diff --git a/yarn-project/simulator/src/avm/serialization/instruction_serialization.test.ts b/yarn-project/simulator/src/avm/serialization/instruction_serialization.test.ts index 3f7d8905c98..8839f86f2ee 100644 --- a/yarn-project/simulator/src/avm/serialization/instruction_serialization.test.ts +++ b/yarn-project/simulator/src/avm/serialization/instruction_serialization.test.ts @@ -1,5 +1,5 @@ import { BufferCursor } from './buffer_cursor.js'; -import { OperandType, deserialize, serialize } from './instruction_serialization.js'; +import { OperandType, deserialize, serializeAs } from './instruction_serialization.js'; class InstA { constructor(private a: number, private b: number, private c: number, private d: bigint, private e: bigint) {} @@ -18,7 +18,7 @@ class InstA { describe('Instruction Serialization', () => { it('Should serialize all types from OperandType[]', () => { const instance = new InstA(0x12, 0x1234, 0x12345678, 0x1234567887654321n, 0x1234567887654321abcdef0000fedcban); - const actual: Buffer = serialize(InstA.wireFormat, instance); + const actual: Buffer = serializeAs(InstA.wireFormat, InstA.opcode, instance); expect(actual).toEqual( Buffer.from( diff --git a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts index e906fb04309..904c9001118 100644 --- a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts @@ -8,20 +8,33 @@ import { BufferCursor } from './buffer_cursor.js'; */ export enum Opcode { // Compute - ADD, - SUB, - MUL, - DIV, - FDIV, - EQ, - LT, - LTE, - AND, - OR, - XOR, + ADD_8, + ADD_16, + SUB_8, + SUB_16, + MUL_8, + MUL_16, + DIV_8, + DIV_16, + FDIV_8, + FDIV_16, + EQ_8, + EQ_16, + LT_8, + LT_16, + LTE_8, + LTE_16, + AND_8, + AND_16, + OR_8, + OR_16, + XOR_8, + XOR_16, NOT, - SHL, - SHR, + SHL_8, + SHL_16, + SHR_8, + SHR_16, CAST, // Execution environment ADDRESS, @@ -33,23 +46,26 @@ export enum Opcode { VERSION, BLOCKNUMBER, TIMESTAMP, - COINBASE, FEEPERL2GAS, FEEPERDAGAS, - BLOCKL2GASLIMIT, - BLOCKDAGASLIMIT, CALLDATACOPY, // Gas L2GASLEFT, DAGASLEFT, // Control flow - JUMP, - JUMPI, + JUMP_16, + JUMPI_16, INTERNALCALL, INTERNALRETURN, // Memory - SET, - MOV, + SET_8, + SET_16, + SET_32, + SET_64, + SET_128, + SET_FF, + MOV_8, + MOV_16, CMOV, // World state SLOAD, @@ -95,6 +111,7 @@ export enum OperandType { UINT32, UINT64, UINT128, + FF, } type OperandNativeType = number | bigint; @@ -107,8 +124,27 @@ const OPERAND_SPEC = new Map OperandNativeType, Oper [OperandType.UINT32, [4, Buffer.prototype.readUint32BE, Buffer.prototype.writeUint32BE]], [OperandType.UINT64, [8, Buffer.prototype.readBigInt64BE, Buffer.prototype.writeBigInt64BE]], [OperandType.UINT128, [16, readBigInt128BE, writeBigInt128BE]], + [OperandType.FF, [32, readBigInt254BE, writeBigInt254BE]], ]); +function readBigInt254BE(this: Buffer): bigint { + const totalBytes = 32; + let ret: bigint = 0n; + for (let i = 0; i < totalBytes; ++i) { + ret <<= 8n; + ret |= BigInt(this.readUint8(i)); + } + return ret; +} + +function writeBigInt254BE(this: Buffer, value: bigint): void { + const totalBytes = 32; + for (let offset = totalBytes - 1; offset >= 0; --offset) { + this.writeUint8(Number(value & 0xffn), offset); + value >>= 8n; + } +} + function readBigInt128BE(this: Buffer): bigint { const totalBytes = 16; let ret: bigint = 0n; @@ -159,12 +195,10 @@ export function deserialize(cursor: BufferCursor | Buffer, operands: OperandType * @param cls The class to be serialized. * @returns */ -export function serialize(operands: OperandType[], cls: any): Buffer { +export function serializeAs(operands: OperandType[], opcode: Opcode, cls: any): Buffer { const chunks: Buffer[] = []; - // TODO: infer opcode not in this loop - assert(cls.constructor.opcode !== undefined && cls.constructor.opcode !== null); - const rawClassValues: any[] = [cls.constructor.opcode, ...Object.values(cls)]; + const rawClassValues: any[] = [opcode, ...Object.values(cls)]; assert( rawClassValues.length === operands.length, `Got ${rawClassValues.length} values but only ${operands.length} serialization operands are specified!`, diff --git a/yarn-project/simulator/src/public/hints_builder.ts b/yarn-project/simulator/src/public/hints_builder.ts index 439aa7a5fa3..637d70d30e9 100644 --- a/yarn-project/simulator/src/public/hints_builder.ts +++ b/yarn-project/simulator/src/public/hints_builder.ts @@ -7,7 +7,6 @@ import { type MAX_NULLIFIERS_PER_TX, type MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, - type MAX_PUBLIC_DATA_HINTS, type MAX_PUBLIC_DATA_READS_PER_TX, type MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, @@ -15,7 +14,6 @@ import { NULLIFIER_TREE_HEIGHT, type Nullifier, PUBLIC_DATA_TREE_HEIGHT, - type PublicDataHint, type PublicDataRead, type PublicDataTreeLeafPreimage, type PublicDataUpdateRequest, @@ -25,7 +23,6 @@ import { buildNullifierNonExistentReadRequestHints, buildPublicDataHint, buildPublicDataHints, - buildPublicDataReadRequestHints, buildSiloedNullifierReadRequestHints, } from '@aztec/circuits.js'; import { makeTuple } from '@aztec/foundation/array'; @@ -91,14 +88,6 @@ export class HintsBuilder { return buildPublicDataHint(this, slot); } - getPublicDataReadRequestHints( - publicDataReads: Tuple, - publicDataUpdateRequests: Tuple, - publicDataHints: Tuple, - ) { - return buildPublicDataReadRequestHints(publicDataReads, publicDataUpdateRequests, publicDataHints); - } - async getNullifierMembershipWitness(nullifier: Fr) { const index = await this.db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer()); if (index === undefined) { diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 1b79581195b..7778147a3ef 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -396,13 +396,11 @@ describe('public_processor', () => { computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.storageContractAddress, contractSlotA), fr(0x101), ), - new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotE), fr(0x301)), new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotC), fr(0x201)), - new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotF), fr(0x351)), new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotD), fr(0x251)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotE), fr(0x301)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotF), fr(0x351)), ]; - // sort increasing by leafIndex - expectedWrites.sort((a, b) => (a.leafIndex.lt(b.leafIndex) ? -1 : 1)); expect(txEffect.publicDataWrites.slice(0, numPublicDataWrites)).toEqual(expectedWrites); // we keep the non-revertible logs @@ -559,7 +557,7 @@ describe('public_processor', () => { PublicExecutionResultBuilder.fromFunctionCall({ from: teardownRequest.callContext.storageContractAddress, tx: makeFunctionCall('', nestedContractAddress, makeSelector(5)), - contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 16)], + contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotC, fr(0x202), 17)], revertReason: new SimulationError('Simulation Failed', []), }).build(teardownResultSettings), ], @@ -598,12 +596,12 @@ describe('public_processor', () => { const numPublicDataWrites = 3; expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toBe(numPublicDataWrites); expect(txEffect.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ - new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), fr(0x151)), new PublicDataWrite( computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.storageContractAddress, contractSlotA), fr(0x101), ), new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotA), fr(0x102)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), fr(0x151)), ]); // we keep the non-revertible logs @@ -714,12 +712,12 @@ describe('public_processor', () => { const numPublicDataWrites = 3; expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toBe(numPublicDataWrites); expect(txEffect.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ - new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), fr(0x151)), new PublicDataWrite( computePublicDataTreeLeafSlot(nonRevertibleRequests[0].callContext.storageContractAddress, contractSlotA), fr(0x101), ), new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotA), fr(0x102)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), fr(0x151)), ]); // we keep the non-revertible logs @@ -892,8 +890,8 @@ describe('public_processor', () => { expect(arrayNonEmptyLength(txEffect.publicDataWrites, PublicDataWrite.isEmpty)).toEqual(numPublicDataWrites); expect(txEffect.publicDataWrites.slice(0, numPublicDataWrites)).toEqual([ new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotB), fr(0x152)), - new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotC), fr(0x201)), new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotA), fr(0x103)), + new PublicDataWrite(computePublicDataTreeLeafSlot(nestedContractAddress, contractSlotC), fr(0x201)), ]); expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(0); expect(txEffect.unencryptedLogs.getTotalLogCount()).toBe(0); diff --git a/yarn-project/simulator/src/public/tail_phase_manager.ts b/yarn-project/simulator/src/public/tail_phase_manager.ts index 155a8fec14a..08b0916d30c 100644 --- a/yarn-project/simulator/src/public/tail_phase_manager.ts +++ b/yarn-project/simulator/src/public/tail_phase_manager.ts @@ -112,12 +112,6 @@ export class TailPhaseManager extends AbstractPhaseManager { pendingPublicDataWrites, ); - const publicDataReadRequestHints = this.hintsBuilder.getPublicDataReadRequestHints( - validationRequests.publicDataReads, - pendingPublicDataWrites, - publicDataHints, - ); - const currentState = await this.db.getStateReference(); return new PublicKernelTailCircuitPrivateInputs( @@ -127,7 +121,6 @@ export class TailPhaseManager extends AbstractPhaseManager { nullifierNonExistentReadRequestHints, l1ToL2MsgReadRequestHints, publicDataHints, - publicDataReadRequestHints, currentState.partial, ); } diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 3d649b5e267..93a8bcc59f2 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -82,6 +82,9 @@ export class TXE implements TypedOracle { private contractAddress: AztecAddress; private msgSender: AztecAddress; private functionSelector = FunctionSelector.fromField(new Fr(0)); + // This will hold the _real_ calldata. That is, the one without the PublicContextInputs. + // TODO: Remove this comment once PublicContextInputs are removed. + private calldata: Fr[] = []; private contractDataOracle: ContractDataOracle; @@ -128,10 +131,20 @@ export class TXE implements TypedOracle { return this.functionSelector; } + getCalldata() { + // TODO: Remove this once PublicContextInputs are removed. + const inputs = this.getPublicContextInputs(); + return [...inputs.toFields(), ...this.calldata]; + } + setMsgSender(msgSender: Fr) { this.msgSender = msgSender; } + setCalldata(calldata: Fr[]) { + this.calldata = calldata; + } + setFunctionSelector(functionSelector: FunctionSelector) { this.functionSelector = functionSelector; } @@ -204,10 +217,10 @@ export class TXE implements TypedOracle { getPublicContextInputs() { const inputs = { - argsHash: new Fr(0), + calldataLength: new Fr(this.calldata.length), isStaticCall: false, toFields: function () { - return [this.argsHash, new Fr(this.isStaticCall)]; + return [this.calldataLength, new Fr(this.isStaticCall)]; }, }; return inputs; @@ -738,6 +751,7 @@ export class TXE implements TypedOracle { this.setMsgSender(this.contractAddress); this.setContractAddress(targetContractAddress); this.setFunctionSelector(functionSelector); + this.setCalldata(args); const callContext = CallContext.empty(); callContext.msgSender = this.msgSender; diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 8b57088aade..5d8edd2800b 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -272,6 +272,11 @@ export class TXEService { return toForeignCallResult([]); } + setCalldata(_length: ForeignCallSingle, calldata: ForeignCallArray) { + (this.typedOracle as TXE).setCalldata(fromArray(calldata)); + return toForeignCallResult([]); + } + getFunctionSelector() { const functionSelector = (this.typedOracle as TXE).getFunctionSelector(); return toForeignCallResult([toSingle(functionSelector.toField())]); @@ -582,6 +587,17 @@ export class TXEService { return toForeignCallResult([]); } + //unconstrained fn calldata_copy_opcode(cdoffset: u32, copy_size: u32) -> [Field; N] {} + avmOpcodeCalldataCopy(cdOffsetInput: ForeignCallSingle, copySizeInput: ForeignCallSingle) { + const cdOffset = fromSingle(cdOffsetInput).toNumber(); + const copySize = fromSingle(copySizeInput).toNumber(); + + const calldata = (this.typedOracle as TXE).getCalldata(); + const calldataSlice = calldata.slice(cdOffset, cdOffset + copySize); + + return toForeignCallResult([toArray(calldataSlice)]); + } + async getPublicKeysAndPartialAddress(address: ForeignCallSingle) { const parsedAddress = AztecAddress.fromField(fromSingle(address)); const { publicKeys, partialAddress } = await this.typedOracle.getCompleteAddress(parsedAddress); diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index cc8bf108dd1..71ff91ca629 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -186,6 +186,7 @@ __metadata: "@aztec/circuits.js": "workspace:^" "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" + "@aztec/l1-artifacts": "workspace:^" "@aztec/protocol-contracts": "workspace:^" "@aztec/types": "workspace:^" "@jest/globals": ^29.5.0 @@ -204,6 +205,7 @@ __metadata: tslib: ^2.4.0 typescript: ^5.0.4 util: ^0.12.5 + viem: ^2.7.15 webpack: ^5.88.2 webpack-cli: ^5.1.4 languageName: unknown @@ -285,6 +287,7 @@ __metadata: dependencies: "@aztec/circuit-types": "workspace:^" "@aztec/circuits.js": "workspace:^" + "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/noir-protocol-circuits-types": "workspace:^" "@aztec/simulator": "workspace:^" @@ -304,6 +307,7 @@ __metadata: ts-node: ^10.9.1 tslib: ^2.4.0 typescript: ^5.0.4 + viem: ^2.7.15 bin: bb-cli: ./dest/bb/index.js languageName: unknown