diff --git a/.aztec-sync-commit b/.aztec-sync-commit index 42ef1037b17..46138f41929 100644 --- a/.aztec-sync-commit +++ b/.aztec-sync-commit @@ -1 +1 @@ -b0d1bab1f02819e7efbe0db73c3c805b5927b66a +fca96007d6055dcf00b72a46630c680fcb6d190d diff --git a/.github/ACVM_NOT_PUBLISHABLE.md b/.github/ACVM_NOT_PUBLISHABLE.md index 33230f8e8d8..06c9505ebae 100644 --- a/.github/ACVM_NOT_PUBLISHABLE.md +++ b/.github/ACVM_NOT_PUBLISHABLE.md @@ -5,7 +5,7 @@ assignees: TomAFrench, Savio-Sou The ACVM crates are currently unpublishable, making a release will NOT push our crates to crates.io. -This is likely due to a crate we depend on bumping its MSRV above our own. Our lockfile is not taken into account when publishing to crates.io (as people downloading our crate don't use it) so we need to be able to use the most up to date versions of our dependencies (including transient dependencies) specified. +This is likely due to a crate we depend on bumping its MSRV above our own. Our lockfile is not taken into account when publishing to crates.io (as people downloading our crate don't use it) so we need to be able to use the most up-to-date versions of our dependencies (including transient dependencies) specified. Check the [MSRV check]({{env.WORKFLOW_URL}}) workflow for details. diff --git a/.github/scripts/backend-barretenberg-build.sh b/.github/scripts/backend-barretenberg-build.sh deleted file mode 100755 index d90995397d8..00000000000 --- a/.github/scripts/backend-barretenberg-build.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -set -eu - -yarn workspace @noir-lang/backend_barretenberg build diff --git a/.github/scripts/backend-barretenberg-test.sh b/.github/scripts/backend-barretenberg-test.sh deleted file mode 100755 index 1bd6f8e410d..00000000000 --- a/.github/scripts/backend-barretenberg-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -set -eu - -yarn workspace @noir-lang/backend_barretenberg test diff --git a/.github/scripts/merge-bench-reports.sh b/.github/scripts/merge-bench-reports.sh new file mode 100755 index 00000000000..23a62874148 --- /dev/null +++ b/.github/scripts/merge-bench-reports.sh @@ -0,0 +1,27 @@ +#!/bin/bash +set -eu + +echo "Merging reports" + +REPORT_NAME=$1 +NAME_PLURAL=""$REPORT_NAME"s" + +combined_reports="[]" + +# Iterate over each report and merge them +for report in ./reports/*; do + # The report is saved under ./$REPORT_NAME_{ matrix_report }/$REPORT_NAME_{ matrix_report }.json + FILE_PATH=$(echo $(ls $report)) + + # Extract the $NAME_PLURAL array from each report and merge it + combined_reports=$(jq '[."'"$NAME_PLURAL"'"[]] + '"$combined_reports" <<< "$(cat "$report/$FILE_PATH")") +done + +combined_reports=$(jq '[."'$NAME_PLURAL'"[]] + '"$combined_reports" <<< "$(cat ./$REPORT_NAME.json)") + +# Wrap the merged memory reports into a new object as to keep the $NAME_PLURAL key +final_report="{\"$NAME_PLURAL\": $combined_reports}" + +echo "$final_report" > $REPORT_NAME.json + +cat $REPORT_NAME.json \ No newline at end of file diff --git a/.github/workflows/cache-cleanup.yml b/.github/workflows/cache-cleanup.yml index cf2b0ec413e..bb05c5454e5 100644 --- a/.github/workflows/cache-cleanup.yml +++ b/.github/workflows/cache-cleanup.yml @@ -12,7 +12,7 @@ on: jobs: cleanup: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Cleanup run: | diff --git a/.github/workflows/deny.yml b/.github/workflows/deny.yml index 8ae7d03e076..11dbc3eef4b 100644 --- a/.github/workflows/deny.yml +++ b/.github/workflows/deny.yml @@ -18,7 +18,7 @@ concurrency: deny-${{ github.head_ref || github.run_id }} jobs: deny: name: deny - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - uses: EmbarkStudios/cargo-deny-action@v1 diff --git a/.github/workflows/docs-dead-links.yml b/.github/workflows/docs-dead-links.yml index 40e948fe2c1..b46c5393f8d 100644 --- a/.github/workflows/docs-dead-links.yml +++ b/.github/workflows/docs-dead-links.yml @@ -13,7 +13,7 @@ concurrency: jobs: markdown-link-check: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@master - uses: gaurav-nelson/github-action-markdown-link-check@v1 diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 9cb6775bfb7..fdd4d25f5ae 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -5,7 +5,7 @@ on: jobs: add_label: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 outputs: has_label: ${{ steps.check-labels.outputs.result }} steps: @@ -49,7 +49,7 @@ jobs: } build_preview: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout code uses: actions/checkout@v4 @@ -80,7 +80,7 @@ jobs: - name: Build docs env: - MATOMO_ENV: staging # not really a secret, it will show in the footer anyway + ENV: staging # not really a secret, it will show in the footer anyway run: yarn workspaces foreach -Rpt --from docs run build - name: Upload artifact @@ -93,7 +93,7 @@ jobs: deploy_preview: needs: [build_preview, add_label] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: pull-requests: write if: needs.add_label.outputs.has_label == 'true' @@ -121,7 +121,7 @@ jobs: add_comment: needs: [deploy_preview] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: pull-requests: write steps: diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index 08c02af519f..f8ebd53dc70 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -15,18 +15,11 @@ concurrency: jobs: clippy: name: cargo clippy - runs-on: ${{ matrix.runner }} + runs-on: ubuntu-22.04 timeout-minutes: 30 env: RUSTFLAGS: -Dwarnings - strategy: - fail-fast: false - matrix: - include: - - runner: ubuntu-latest - target: x86_64-unknown-linux-gnu - steps: - name: Checkout uses: actions/checkout@v4 @@ -34,24 +27,47 @@ jobs: - name: Setup toolchain uses: dtolnay/rust-toolchain@1.74.1 with: - targets: ${{ matrix.target }} + targets: x86_64-unknown-linux-gnu components: clippy, rustfmt - uses: Swatinem/rust-cache@v2 with: - key: ${{ matrix.target }} + key: x86_64-unknown-linux-gnu cache-on-failure: true save-if: ${{ github.event_name != 'merge_group' }} - name: Run `cargo clippy` run: cargo clippy --all-targets --workspace --locked --release + rustfmt: + name: cargo fmt + runs-on: ubuntu-22.04 + timeout-minutes: 30 + env: + RUSTFLAGS: -Dwarnings + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.74.1 + with: + targets: x86_64-unknown-linux-gnu + components: clippy, rustfmt + + - uses: Swatinem/rust-cache@v2 + with: + key: x86_64-unknown-linux-gnu + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + - name: Run `cargo fmt` run: cargo fmt --all --check eslint: name: eslint - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -88,7 +104,6 @@ jobs: run: | mkdir dist cp ./target/release/nargo ./dist/nargo - 7z a -ttar -so -an ./dist/* | 7z a -si ./nargo-x86_64-unknown-linux-gnu.tar.gz - name: Upload artifact uses: actions/upload-artifact@v4 @@ -100,7 +115,7 @@ jobs: nargo_fmt: needs: [build-nargo] name: Nargo fmt - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: diff --git a/.github/workflows/gates_report.yml b/.github/workflows/gates_report.yml deleted file mode 100644 index 0b0a527b69e..00000000000 --- a/.github/workflows/gates_report.yml +++ /dev/null @@ -1,94 +0,0 @@ -name: Report gates diff - -on: - push: - branches: - - master - pull_request: - -jobs: - build-nargo: - runs-on: ubuntu-latest - strategy: - matrix: - target: [x86_64-unknown-linux-gnu] - - steps: - - name: Checkout Noir repo - uses: actions/checkout@v4 - - - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.74.1 - - - uses: Swatinem/rust-cache@v2 - with: - key: ${{ matrix.target }} - cache-on-failure: true - save-if: ${{ github.event_name != 'merge_group' }} - - - name: Build Nargo - run: cargo build --package nargo_cli --release - - - name: Package artifacts - run: | - mkdir dist - cp ./target/release/nargo ./dist/nargo - 7z a -ttar -so -an ./dist/* | 7z a -si ./nargo-x86_64-unknown-linux-gnu.tar.gz - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: nargo - path: ./dist/* - retention-days: 3 - - - compare_gates_reports: - needs: [build-nargo] - runs-on: ubuntu-latest - permissions: - pull-requests: write - - steps: - - uses: actions/checkout@v4 - - - name: Install `bb` - run: | - ./scripts/install_bb.sh - echo "$HOME/.bb/" >> $GITHUB_PATH - - - name: Download nargo binary - uses: actions/download-artifact@v4 - with: - name: nargo - path: ./nargo - - - name: Set nargo on PATH - run: | - nargo_binary="${{ github.workspace }}/nargo/nargo" - chmod +x $nargo_binary - echo "$(dirname $nargo_binary)" >> $GITHUB_PATH - export PATH="$PATH:$(dirname $nargo_binary)" - nargo -V - - - name: Generate gates report - working-directory: ./test_programs - run: | - ./rebuild.sh - ./gates_report.sh - mv gates_report.json ../gates_report.json - - - name: Compare gates reports - id: gates_diff - uses: noir-lang/noir-gates-diff@1931aaaa848a1a009363d6115293f7b7fc72bb87 - with: - report: gates_report.json - summaryQuantile: 0.9 # only display the 10% most significant circuit size diffs in the summary (defaults to 20%) - - - name: Add gates diff to sticky comment - if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' - uses: marocchino/sticky-pull-request-comment@v2 - with: - # delete the comment in case changes no longer impact circuit sizes - delete: ${{ !steps.gates_diff.outputs.markdown }} - message: ${{ steps.gates_diff.outputs.markdown }} diff --git a/.github/workflows/gates_report_brillig.yml b/.github/workflows/gates_report_brillig.yml deleted file mode 100644 index e7ec30923f0..00000000000 --- a/.github/workflows/gates_report_brillig.yml +++ /dev/null @@ -1,92 +0,0 @@ -name: Report Brillig bytecode size diff - -on: - push: - branches: - - master - pull_request: - -jobs: - build-nargo: - runs-on: ubuntu-latest - strategy: - matrix: - target: [x86_64-unknown-linux-gnu] - - steps: - - name: Checkout Noir repo - uses: actions/checkout@v4 - - - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.74.1 - - - uses: Swatinem/rust-cache@v2 - with: - key: ${{ matrix.target }} - cache-on-failure: true - save-if: ${{ github.event_name != 'merge_group' }} - - - name: Build Nargo - run: cargo build --package nargo_cli --release - - - name: Package artifacts - run: | - mkdir dist - cp ./target/release/nargo ./dist/nargo - 7z a -ttar -so -an ./dist/* | 7z a -si ./nargo-x86_64-unknown-linux-gnu.tar.gz - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: nargo - path: ./dist/* - retention-days: 3 - - compare_brillig_bytecode_size_reports: - needs: [build-nargo] - runs-on: ubuntu-latest - permissions: - pull-requests: write - - steps: - - uses: actions/checkout@v4 - - - name: Download nargo binary - uses: actions/download-artifact@v4 - with: - name: nargo - path: ./nargo - - - name: Set nargo on PATH - run: | - nargo_binary="${{ github.workspace }}/nargo/nargo" - chmod +x $nargo_binary - echo "$(dirname $nargo_binary)" >> $GITHUB_PATH - export PATH="$PATH:$(dirname $nargo_binary)" - nargo -V - - - name: Generate Brillig bytecode size report - working-directory: ./test_programs - run: | - chmod +x gates_report_brillig.sh - ./gates_report_brillig.sh - mv gates_report_brillig.json ../gates_report_brillig.json - - - name: Compare Brillig bytecode size reports - id: brillig_bytecode_diff - uses: noir-lang/noir-gates-diff@d88f7523b013b9edd3f31c5cfddaef87a3fe1b48 - with: - report: gates_report_brillig.json - header: | - # Changes to Brillig bytecode sizes - brillig_report: true - summaryQuantile: 0.9 # only display the 10% most significant bytecode size diffs in the summary (defaults to 20%) - - - name: Add bytecode size diff to sticky comment - if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' - uses: marocchino/sticky-pull-request-comment@v2 - with: - header: brillig - # delete the comment in case changes no longer impact brillig bytecode sizes - delete: ${{ !steps.brillig_bytecode_diff.outputs.markdown }} - message: ${{ steps.brillig_bytecode_diff.outputs.markdown }} \ No newline at end of file diff --git a/.github/workflows/lockfile.yml b/.github/workflows/lockfile.yml deleted file mode 100644 index 190e01745af..00000000000 --- a/.github/workflows/lockfile.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Lockfile check - -on: - pull_request: - -# This will cancel previous runs when a branch or PR is updated -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} - cancel-in-progress: true - -jobs: - yarn-lock: - runs-on: ubuntu-latest - timeout-minutes: 30 - - steps: - - name: Checkout - uses: actions/checkout@v4 - - # Errors if installation would result in modifications to yarn.lock - - name: Install - run: yarn --immutable - shell: bash diff --git a/.github/workflows/publish-acvm.yml b/.github/workflows/publish-acvm.yml index feb4d4216c3..fb2e2001e40 100644 --- a/.github/workflows/publish-acvm.yml +++ b/.github/workflows/publish-acvm.yml @@ -10,7 +10,7 @@ on: jobs: publish: name: Publish in order - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout sources uses: actions/checkout@v4 diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index 8896e613608..16959256d2a 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -10,7 +10,7 @@ on: jobs: publish-docs: name: Publish docs - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout release branch diff --git a/.github/workflows/publish-es-packages.yml b/.github/workflows/publish-es-packages.yml index 682fed69c7b..e629ae1f133 100644 --- a/.github/workflows/publish-es-packages.yml +++ b/.github/workflows/publish-es-packages.yml @@ -16,7 +16,7 @@ run-name: Publish ES Packages from ${{ inputs.noir-ref }} under @${{ inputs.npm- jobs: build-noirc_abi_wasm: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout Noir repo uses: actions/checkout@v4 @@ -50,7 +50,7 @@ jobs: retention-days: 10 build-noir_wasm: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout sources uses: actions/checkout@v4 @@ -87,7 +87,7 @@ jobs: retention-days: 3 build-acvm_js: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout sources uses: actions/checkout@v4 @@ -121,7 +121,7 @@ jobs: retention-days: 3 publish-es-packages: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-acvm_js, build-noirc_abi_wasm, build-noir_wasm] steps: - name: Checkout sources diff --git a/.github/workflows/publish-nargo.yml b/.github/workflows/publish-nargo.yml index 55ba754e6ae..fa0b6f2d9fb 100644 --- a/.github/workflows/publish-nargo.yml +++ b/.github/workflows/publish-nargo.yml @@ -23,7 +23,7 @@ permissions: jobs: build-apple-darwin: - runs-on: macos-12 + runs-on: macos-14 env: CROSS_CONFIG: ${{ github.workspace }}/.github/Cross.toml NIGHTLY_RELEASE: ${{ inputs.tag == '' }} @@ -41,7 +41,7 @@ jobs: - name: Setup for Apple Silicon if: matrix.target == 'aarch64-apple-darwin' run: | - sudo xcode-select -s /Applications/Xcode_13.2.1.app/Contents/Developer/ + sudo xcode-select -s /Applications/Xcode_15.4.0.app/Contents/Developer/ echo "SDKROOT=$(xcrun -sdk macosx$(sw_vers -productVersion) --show-sdk-path)" >> $GITHUB_ENV echo "MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx$(sw_vers -productVersion) --show-sdk-platform-version)" >> $GITHUB_ENV diff --git a/.github/workflows/publish-nightly.yml b/.github/workflows/publish-nightly.yml index f5c013883bb..2eef9ab60f7 100644 --- a/.github/workflows/publish-nightly.yml +++ b/.github/workflows/publish-nightly.yml @@ -7,7 +7,7 @@ on: jobs: dispatch-publish-es: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Dispatch to publish-nargo uses: benc-uk/workflow-dispatch@v1 diff --git a/.github/workflows/pull-request-title.yml b/.github/workflows/pull-request-title.yml index 7e9b729da28..41922bd32ab 100644 --- a/.github/workflows/pull-request-title.yml +++ b/.github/workflows/pull-request-title.yml @@ -15,7 +15,7 @@ permissions: jobs: conventional-title: name: Validate PR title is Conventional Commit - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Check title if: github.event_name == 'pull_request_target' @@ -30,7 +30,7 @@ jobs: force-push-comment: name: Warn external contributors about force-pushing - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 if: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != 'noir-lang/noir' }} permissions: pull-requests: write diff --git a/.github/workflows/recrawler.yml b/.github/workflows/recrawler.yml index ee832e273a1..808e5819353 100644 --- a/.github/workflows/recrawler.yml +++ b/.github/workflows/recrawler.yml @@ -7,7 +7,7 @@ on: jobs: algolia_recrawl: name: Algolia Recrawl - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Algolia crawler creation and crawl uses: algolia/algoliasearch-crawler-github-actions@v1.1.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5124592a3fe..bbe9a7fff62 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,20 +11,19 @@ jobs: outputs: release-pr: ${{ steps.release.outputs.pr }} tag-name: ${{ steps.release.outputs.tag_name }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Run release-please id: release - uses: google-github-actions/release-please-action@v3 + uses: googleapis/release-please-action@v4 with: token: ${{ secrets.NOIR_RELEASES_TOKEN }} - command: manifest update-acvm-workspace-package-versions: name: Update acvm workspace package versions needs: [release-please] if: ${{ needs.release-please.outputs.release-pr }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout release branch uses: actions/checkout@v4 @@ -67,7 +66,7 @@ jobs: name: Update docs needs: [release-please, update-acvm-workspace-package-versions] if: ${{ needs.release-please.outputs.release-pr }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout release branch @@ -111,7 +110,7 @@ jobs: release-end: name: Release End - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # We want this job to always run (even if the dependant jobs fail) as we need apply changes to the sticky comment. if: ${{ always() }} @@ -146,7 +145,7 @@ jobs: name: Build binaries needs: [release-please] if: ${{ needs.release-please.outputs.tag-name }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Dispatch to publish workflow uses: benc-uk/workflow-dispatch@v1 @@ -161,7 +160,7 @@ jobs: name: Publish ES packages needs: [release-please] if: ${{ needs.release-please.outputs.tag-name }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Dispatch to publish-es-packages uses: benc-uk/workflow-dispatch@v1 @@ -175,7 +174,7 @@ jobs: name: Publish acvm needs: [release-please] if: ${{ needs.release-please.outputs.tag-name }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Dispatch to publish-acvm diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml new file mode 100644 index 00000000000..0a03add8338 --- /dev/null +++ b/.github/workflows/reports.yml @@ -0,0 +1,492 @@ +name: Reports + +on: + push: + branches: + - master + pull_request: + +jobs: + build-nargo: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout Noir repo + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.74.1 + + - uses: Swatinem/rust-cache@v2 + with: + key: x86_64-unknown-linux-gnu + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Build Nargo + run: cargo build --package nargo_cli --release + + - name: Package artifacts + run: | + mkdir dist + cp ./target/release/nargo ./dist/nargo + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: nargo + path: ./dist/* + retention-days: 3 + + compare_gates_reports: + name: Circuit sizes + needs: [build-nargo] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Install `bb` + run: | + ./scripts/install_bb.sh + echo "$HOME/.bb/" >> $GITHUB_PATH + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Generate gates report + working-directory: ./test_programs + run: | + ./rebuild.sh + ./gates_report.sh + mv gates_report.json ../gates_report.json + + - name: Compare gates reports + id: gates_diff + uses: noir-lang/noir-gates-diff@1931aaaa848a1a009363d6115293f7b7fc72bb87 + with: + report: gates_report.json + summaryQuantile: 0.9 # only display the 10% most significant circuit size diffs in the summary (defaults to 20%) + + - name: Add gates diff to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + # delete the comment in case changes no longer impact circuit sizes + delete: ${{ !steps.gates_diff.outputs.markdown }} + message: ${{ steps.gates_diff.outputs.markdown }} + + compare_brillig_bytecode_size_reports: + name: Brillig bytecode sizes + needs: [build-nargo] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Generate Brillig bytecode size report + working-directory: ./test_programs + run: | + ./gates_report_brillig.sh + mv gates_report_brillig.json ../gates_report_brillig.json + + - name: Compare Brillig bytecode size reports + id: brillig_bytecode_diff + uses: noir-lang/noir-gates-diff@d88f7523b013b9edd3f31c5cfddaef87a3fe1b48 + with: + report: gates_report_brillig.json + header: | + # Changes to Brillig bytecode sizes + brillig_report: true + summaryQuantile: 0.9 # only display the 10% most significant bytecode size diffs in the summary (defaults to 20%) + + - name: Add bytecode size diff to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: brillig + # delete the comment in case changes no longer impact brillig bytecode sizes + delete: ${{ !steps.brillig_bytecode_diff.outputs.markdown }} + message: ${{ steps.brillig_bytecode_diff.outputs.markdown }} + + compare_brillig_execution_reports: + name: Brillig execution trace sizes + needs: [build-nargo] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Generate Brillig execution report + working-directory: ./test_programs + run: | + ./gates_report_brillig_execution.sh + mv gates_report_brillig_execution.json ../gates_report_brillig_execution.json + + - name: Compare Brillig execution reports + id: brillig_execution_diff + uses: noir-lang/noir-gates-diff@d88f7523b013b9edd3f31c5cfddaef87a3fe1b48 + with: + report: gates_report_brillig_execution.json + header: | + # Changes to number of Brillig opcodes executed + brillig_report: true + summaryQuantile: 0.9 # only display the 10% most significant bytecode size diffs in the summary (defaults to 20%) + + - name: Add bytecode size diff to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: brillig_execution + # delete the comment in case changes no longer impact brillig bytecode sizes + delete: ${{ !steps.brillig_execution_diff.outputs.markdown }} + message: ${{ steps.brillig_execution_diff.outputs.markdown }} + + generate_memory_report: + name: Peak memory usage + needs: [build-nargo] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Generate Memory report + working-directory: ./test_programs + run: | + ./memory_report.sh + mv memory_report.json ../memory_report.json + + - name: Upload memory report + uses: actions/upload-artifact@v4 + with: + name: in_progress_memory_report + path: memory_report.json + retention-days: 3 + overwrite: true + + generate_compilation_report: + name: Compilation time + needs: [build-nargo] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Generate Compilation report + working-directory: ./test_programs + run: | + ./compilation_report.sh + cat compilation_report.json + mv compilation_report.json ../compilation_report.json + + - name: Upload compilation report + uses: actions/upload-artifact@v4 + with: + name: in_progress_compilation_report + path: compilation_report.json + retention-days: 3 + overwrite: true + + external_repo_compilation_report: + needs: [build-nargo] + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + include: + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-contracts } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/parity-root } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-inner } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-tail } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-reset } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-private } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-public } + + name: External repo compilation report - ${{ matrix.project.repo }}/${{ matrix.project.path }} + steps: + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - uses: actions/checkout@v4 + with: + path: scripts + sparse-checkout: | + test_programs/compilation_report.sh + sparse-checkout-cone-mode: false + + - name: Checkout + uses: actions/checkout@v4 + with: + repository: ${{ matrix.project.repo }} + path: test-repo + ref: ${{ matrix.project.ref }} + + - name: Generate compilation report + working-directory: ./test-repo/${{ matrix.project.path }} + run: | + mv /home/runner/work/noir/noir/scripts/test_programs/compilation_report.sh ./compilation_report.sh + chmod +x ./compilation_report.sh + ./compilation_report.sh 1 + + - name: Move compilation report + id: report + shell: bash + run: | + PACKAGE_NAME=${{ matrix.project.path }} + PACKAGE_NAME=$(basename $PACKAGE_NAME) + mv ./test-repo/${{ matrix.project.path }}/compilation_report.json ./compilation_report_$PACKAGE_NAME.json + echo "compilation_report_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT + + - name: Upload compilation report + uses: actions/upload-artifact@v4 + with: + name: compilation_report_${{ steps.report.outputs.compilation_report_name }} + path: compilation_report_${{ steps.report.outputs.compilation_report_name }}.json + retention-days: 3 + overwrite: true + + upload_compilation_report: + name: Upload compilation report + needs: [generate_compilation_report, external_repo_compilation_report] + # We want this job to run even if one variation of the matrix in `external_repo_compilation_report` fails + if: always() + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download initial compilation report + uses: actions/download-artifact@v4 + with: + name: in_progress_compilation_report + + - name: Download matrix compilation reports + uses: actions/download-artifact@v4 + with: + pattern: compilation_report_* + path: ./reports + + - name: Merge compilation reports using jq + run: | + mv ./.github/scripts/merge-bench-reports.sh merge-bench-reports.sh + ./merge-bench-reports.sh compilation_report + + - name: Parse compilation report + id: compilation_report + uses: noir-lang/noir-bench-report@0d7464a8c39170523932d7846b6e6b458a294aea + with: + report: compilation_report.json + header: | + # Compilation Report + memory_report: false + + - name: Add memory report to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: compilation + message: ${{ steps.compilation_report.outputs.markdown }} + + external_repo_memory_report: + needs: [build-nargo] + runs-on: ubuntu-latest + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + include: + # TODO: Bring this report back under a flag. The `noir-contracts` report takes just under 30 minutes. + # - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-contracts } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/parity-root } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-inner } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-reset } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-tail } + + name: External repo memory report - ${{ matrix.project.repo }}/${{ matrix.project.path }} + steps: + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - uses: actions/checkout@v4 + with: + path: scripts + sparse-checkout: | + test_programs/memory_report.sh + sparse-checkout-cone-mode: false + + - name: Checkout + uses: actions/checkout@v4 + with: + repository: ${{ matrix.project.repo }} + path: test-repo + ref: ${{ matrix.project.ref }} + + - name: Generate compilation report + working-directory: ./test-repo/${{ matrix.project.path }} + run: | + mv /home/runner/work/noir/noir/scripts/test_programs/memory_report.sh ./memory_report.sh + chmod +x ./memory_report.sh + ./memory_report.sh 1 + + - name: Move compilation report + id: report + shell: bash + run: | + PACKAGE_NAME=${{ matrix.project.path }} + PACKAGE_NAME=$(basename $PACKAGE_NAME) + mv ./test-repo/${{ matrix.project.path }}/memory_report.json ./memory_report_$PACKAGE_NAME.json + echo "memory_report_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT + + - name: Upload memory report + uses: actions/upload-artifact@v4 + with: + name: memory_report_${{ steps.report.outputs.memory_report_name }} + path: memory_report_${{ steps.report.outputs.memory_report_name }}.json + retention-days: 3 + overwrite: true + + upload_memory_report: + name: Upload memory report + needs: [generate_memory_report, external_repo_memory_report] + # We want this job to run even if one variation of the matrix in `external_repo_memory_report` fails + if: always() + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download initial memory report + uses: actions/download-artifact@v4 + with: + name: in_progress_memory_report + + - name: Download matrix memory reports + uses: actions/download-artifact@v4 + with: + pattern: memory_report_* + path: ./reports + + - name: Merge memory reports using jq + run: | + mv ./.github/scripts/merge-bench-reports.sh merge-bench-reports.sh + ./merge-bench-reports.sh memory_report + + - name: Parse memory report + id: memory_report + uses: noir-lang/noir-bench-report@0d7464a8c39170523932d7846b6e6b458a294aea + with: + report: memory_report.json + header: | + # Memory Report + memory_report: true + + - name: Add memory report to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: memory + message: ${{ steps.memory_report.outputs.markdown }} diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index 83d67325775..2b9a1461231 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -10,7 +10,7 @@ concurrency: jobs: code: name: Code - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout sources uses: actions/checkout@v4 @@ -25,7 +25,7 @@ jobs: docs: name: Documentation - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout sources uses: actions/checkout@v4 diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml index ff894f061ee..dde0deed0cf 100644 --- a/.github/workflows/test-js-packages.yml +++ b/.github/workflows/test-js-packages.yml @@ -13,6 +13,19 @@ concurrency: cancel-in-progress: true jobs: + yarn-lock: + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Errors if installation would result in modifications to yarn.lock + - name: Install + run: yarn --immutable + shell: bash + build-nargo: runs-on: ubuntu-22.04 timeout-minutes: 30 @@ -47,7 +60,7 @@ jobs: retention-days: 3 build-noirc-abi: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -73,14 +86,13 @@ jobs: uses: actions/upload-artifact@v4 with: name: noirc_abi_wasm - path: | + path: | ./tooling/noirc_abi_wasm/nodejs ./tooling/noirc_abi_wasm/web retention-days: 10 - build-noir-wasm: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -115,7 +127,7 @@ jobs: retention-days: 3 build-acvm-js: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -149,7 +161,7 @@ jobs: test-acvm_js-node: needs: [build-acvm-js] name: ACVM JS (Node.js) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -171,7 +183,7 @@ jobs: test-acvm_js-browser: needs: [build-acvm-js] name: ACVM JS (Browser) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -196,7 +208,7 @@ jobs: test-noirc-abi: needs: [build-noirc-abi] name: noirc_abi - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -224,7 +236,7 @@ jobs: test-noir-js: needs: [build-nargo, build-acvm-js, build-noirc-abi] name: Noir JS - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -263,9 +275,6 @@ jobs: - name: Build noir_js_types run: yarn workspace @noir-lang/types build - - name: Build barretenberg wrapper - run: yarn workspace @noir-lang/backend_barretenberg build - - name: Run noir_js tests run: | yarn workspace @noir-lang/noir_js build @@ -274,7 +283,7 @@ jobs: test-noir-wasm: needs: [build-noir-wasm, build-nargo] name: noir_wasm - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -318,7 +327,7 @@ jobs: test-noir-codegen: needs: [build-acvm-js, build-noirc-abi, build-nargo] name: noir_codegen - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -365,7 +374,7 @@ jobs: test-integration-node: name: Integration Tests (Node) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-acvm-js, build-noir-wasm, build-nargo, build-noirc-abi] timeout-minutes: 30 @@ -416,7 +425,7 @@ jobs: - name: Setup `integration-tests` run: | # Note the lack of spaces between package names. - PACKAGES_TO_BUILD="@noir-lang/types,@noir-lang/backend_barretenberg,@noir-lang/noir_js" + PACKAGES_TO_BUILD="@noir-lang/types,@noir-lang/noir_js" yarn workspaces foreach -vtp --from "{$PACKAGES_TO_BUILD}" run build - name: Run `integration-tests` @@ -426,7 +435,7 @@ jobs: test-integration-browser: name: Integration Tests (Browser) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-acvm-js, build-noir-wasm, build-noirc-abi] timeout-minutes: 30 @@ -461,7 +470,7 @@ jobs: - name: Setup `integration-tests` run: | # Note the lack of spaces between package names. - PACKAGES_TO_BUILD="@noir-lang/types,@noir-lang/backend_barretenberg,@noir-lang/noir_js" + PACKAGES_TO_BUILD="@noir-lang/types,@noir-lang/noir_js" yarn workspaces foreach -vtp --from "{$PACKAGES_TO_BUILD}" run build - name: Run `integration-tests` @@ -471,7 +480,7 @@ jobs: test-examples: name: Example scripts - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-nargo] timeout-minutes: 30 @@ -481,6 +490,9 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1.2.0 + with: + version: nightly-8660e5b941fe7f4d67e246cfd3dafea330fb53b1 + - name: Install `bb` run: | @@ -509,23 +521,45 @@ jobs: working-directory: ./examples/codegen_verifier run: ./test.sh + critical-library-list: + name: Load critical library list + runs-on: ubuntu-22.04 + outputs: + libraries: ${{ steps.get_critical_libraries.outputs.libraries }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build list of libraries + id: get_critical_libraries + run: | + LIBRARIES=$(grep -Po "^https://github.com/\K.+" ./CRITICAL_NOIR_LIBRARIES | jq -R -s -c 'split("\n") | map(select(. != "")) | map({ repo: ., path: ""})') + echo "libraries=$LIBRARIES" + echo "libraries=$LIBRARIES" >> $GITHUB_OUTPUT + env: + GH_TOKEN: ${{ github.token }} + external-repo-checks: - needs: [build-nargo] - runs-on: ubuntu-latest + needs: [build-nargo, critical-library-list] + runs-on: ubuntu-22.04 # Only run when 'run-external-checks' label is present if: contains(github.event.pull_request.labels.*.name, 'run-external-checks') timeout-minutes: 30 strategy: fail-fast: false matrix: - project: - # Disabled as these are currently failing with many visibility errors - - { repo: AztecProtocol/aztec-nr, path: ./ } - - { repo: AztecProtocol/aztec-packages, path: ./noir-projects/noir-contracts } - # Disabled as aztec-packages requires a setup-step in order to generate a `Nargo.toml` - #- { repo: AztecProtocol/aztec-packages, path: ./noir-projects/noir-protocol-circuits } - - { repo: zac-williamson/noir-edwards, path: ./, ref: 037e44b2ee8557c51f6aef9bb9d63ea9e32722d1 } - name: Check external repo - ${{ matrix.project.repo }} + project: ${{ fromJson( needs.critical-library-list.outputs.libraries )}} + include: + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/aztec-nr } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-contracts } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/parity-lib } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-lib } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/reset-kernel-lib } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-lib } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/types } + + name: Check external repo - ${{ matrix.project.repo }}/${{ matrix.project.path }} steps: - name: Checkout uses: actions/checkout@v4 @@ -554,18 +588,22 @@ jobs: # Github actions seems to not expand "**" in globs by default. shopt -s globstar sed -i '/^compiler_version/d' ./**/Nargo.toml - - name: Run nargo check + + - name: Run nargo test working-directory: ./test-repo/${{ matrix.project.path }} - run: nargo check + run: nargo test -q --silence-warnings + env: + NARGO_IGNORE_TEST_FAILURES_FROM_FOREIGN_CALLS: true # This is a job which depends on all test jobs and reports the overall status. # This allows us to add/remove test jobs without having to update the required workflows. tests-end: name: End - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping. if: ${{ always() }} - needs: + needs: + - yarn-lock - test-acvm_js-node - test-acvm_js-browser - test-noirc-abi diff --git a/.github/workflows/test-rust-workspace-msrv.yml b/.github/workflows/test-rust-workspace-msrv.yml index ae016169830..6fd71eb56a2 100644 --- a/.github/workflows/test-rust-workspace-msrv.yml +++ b/.github/workflows/test-rust-workspace-msrv.yml @@ -21,7 +21,7 @@ concurrency: jobs: build-test-artifacts: name: Build test artifacts - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -62,7 +62,7 @@ jobs: run-tests: name: "Run tests (partition ${{matrix.partition}})" - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-test-artifacts] strategy: fail-fast: false @@ -87,6 +87,7 @@ jobs: name: nextest-archive - name: Run tests run: | + RUST_MIN_STACK=8388608 \ cargo nextest run --archive-file nextest-archive.tar.zst \ --partition count:${{ matrix.partition }}/4 \ --no-fail-fast @@ -95,7 +96,7 @@ jobs: # This allows us to add/remove test jobs without having to update the required workflows. tests-end: name: Rust End - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping. if: ${{ always() }} needs: diff --git a/.github/workflows/test-rust-workspace.yml b/.github/workflows/test-rust-workspace.yml index 1f3ee5e2268..1514270ff56 100644 --- a/.github/workflows/test-rust-workspace.yml +++ b/.github/workflows/test-rust-workspace.yml @@ -15,7 +15,7 @@ concurrency: jobs: build-test-artifacts: name: Build test artifacts - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 steps: @@ -49,7 +49,7 @@ jobs: run-tests: name: "Run tests (partition ${{matrix.partition}})" - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [build-test-artifacts] strategy: fail-fast: false @@ -74,6 +74,7 @@ jobs: name: nextest-archive - name: Run tests run: | + RUST_MIN_STACK=8388608 \ cargo nextest run --archive-file nextest-archive.tar.zst \ --partition count:${{ matrix.partition }}/4 \ --no-fail-fast @@ -82,7 +83,7 @@ jobs: # This allows us to add/remove test jobs without having to update the required workflows. tests-end: name: Rust End - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping. if: ${{ always() }} needs: diff --git a/.gitignore b/.gitignore index aeb7d8757c4..8442d688fbf 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,8 @@ tooling/noir_js/lib gates_report.json gates_report_brillig.json +gates_report_brillig_execution.json +compilation_report.json # Github Actions scratch space # This gives a location to download artifacts into the repository in CI without making git dirty. diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8be8ad41ac0..b5c8da729e3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,4 +1,3 @@ { - ".": "0.34.0", - "acvm-repo": "0.50.0" + ".": "1.0.0-beta.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 9779d7ab964..19d36b885ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,377 @@ # Changelog +## [1.0.0-beta.0](https://github.com/noir-lang/noir/compare/v0.39.0...v1.0.0-beta.0) (2024-11-22) + + +### ⚠ BREAKING CHANGES + +* Require types of globals to be specified ([#6592](https://github.com/noir-lang/noir/issues/6592)) +* remove eddsa from stdlib ([#6591](https://github.com/noir-lang/noir/issues/6591)) + +### Features + +* Add `array_refcount` and `slice_refcount` builtins for debugging ([#6584](https://github.com/noir-lang/noir/issues/6584)) ([45eb756](https://github.com/noir-lang/noir/commit/45eb7568d56b2d254453b85f236d554232aa5df9)) +* Avoid incrementing reference counts in some cases ([#6568](https://github.com/noir-lang/noir/issues/6568)) ([01c4a9f](https://github.com/noir-lang/noir/commit/01c4a9fb62ffe2190c73f0d5b12933d2eb8f6b5d)) +* **ssa:** Loop invariant code motion ([#6563](https://github.com/noir-lang/noir/issues/6563)) ([7216f08](https://github.com/noir-lang/noir/commit/7216f0829dcece948d3243471e6d57380522e997)) +* Trait aliases ([#6431](https://github.com/noir-lang/noir/issues/6431)) ([68c32b4](https://github.com/noir-lang/noir/commit/68c32b4ffd9b069fe4b119327dbf4018c17ab9d4)) +* Try to inline brillig calls with all constant arguments ([#6548](https://github.com/noir-lang/noir/issues/6548)) ([e4c66b9](https://github.com/noir-lang/noir/commit/e4c66b91d42b20d17837fe5e7c32c9a83b6ab354)) + + +### Bug Fixes + +* Consider prereleases to be compatible with pre-1.0.0 releases ([#6580](https://github.com/noir-lang/noir/issues/6580)) ([013e200](https://github.com/noir-lang/noir/commit/013e2000f1d7e7346b5cac0427732d545f501444)) +* Correct type when simplifying `derive_pedersen_generators` ([#6579](https://github.com/noir-lang/noir/issues/6579)) ([efa5cc4](https://github.com/noir-lang/noir/commit/efa5cc4bf173b0ce49f47b1954165a2bdb276792)) +* Don't report visibility errors when elaborating comptime value ([#6498](https://github.com/noir-lang/noir/issues/6498)) ([3c361c9](https://github.com/noir-lang/noir/commit/3c361c9f78a5d9de1b1bcb5a839d3bc481f89898)) +* Parse a bit more SSA stuff ([#6599](https://github.com/noir-lang/noir/issues/6599)) ([0a6207d](https://github.com/noir-lang/noir/commit/0a6207dde6c744e2853905014e70d33b29b3e53b)) +* Preserve newlines between comments when formatting statements ([#6601](https://github.com/noir-lang/noir/issues/6601)) ([d94eb08](https://github.com/noir-lang/noir/commit/d94eb085adf2cdd8f0e80d9cfd712c19c8810974)) +* Remove `compiler_version` from new `Nargo.toml` ([#6590](https://github.com/noir-lang/noir/issues/6590)) ([df8f2ee](https://github.com/noir-lang/noir/commit/df8f2eee5c27d3cd4b6128056afdd9bd4a0322fe)) + + +### Miscellaneous Chores + +* Remove eddsa from stdlib ([#6591](https://github.com/noir-lang/noir/issues/6591)) ([8e046af](https://github.com/noir-lang/noir/commit/8e046afbbe3fba06c1e177f74aacefdd1bf871b6)) +* Require types of globals to be specified ([#6592](https://github.com/noir-lang/noir/issues/6592)) ([8ff4efd](https://github.com/noir-lang/noir/commit/8ff4efda5589d39d31ced31c6575f43133fceebc)) +* Switch to 1.0.0-beta versioning ([#6503](https://github.com/noir-lang/noir/issues/6503)) ([44e7dc1](https://github.com/noir-lang/noir/commit/44e7dc1037b047db866af675cd8caa0fc8aee324)) + +## [0.39.0](https://github.com/noir-lang/noir/compare/v0.38.0...v0.39.0) (2024-11-19) + + +### ⚠ BREAKING CHANGES + +* Remove `recursive` from ACIR format; add them to API and CLI (https://github.com/AztecProtocol/aztec-packages/pull/9479) + +### Features + +* Avoid unnecessary ssa passes while loop unrolling ([#6509](https://github.com/noir-lang/noir/issues/6509)) ([f81c649](https://github.com/noir-lang/noir/commit/f81c6497ff88e1cc6f3f5c183e679090c6433c65)) +* Deduplicate instructions across blocks ([#6499](https://github.com/noir-lang/noir/issues/6499)) ([b65a63d](https://github.com/noir-lang/noir/commit/b65a63d8d898e46cc686baa500f0b8070e45df14)) +* Encode static error strings in the ABI (https://github.com/AztecProtocol/aztec-packages/pull/9552) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) +* Parallelize DIE pass (https://github.com/AztecProtocol/aztec-packages/pull/9933) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) +* **profiler:** Reduce memory in Brillig execution flamegraph ([#6538](https://github.com/noir-lang/noir/issues/6538)) ([1cad7c8](https://github.com/noir-lang/noir/commit/1cad7c887893ebfb5de57a71d7965c8b88158a14)) +* Simplify constant MSM calls in SSA ([#6547](https://github.com/noir-lang/noir/issues/6547)) ([f291e37](https://github.com/noir-lang/noir/commit/f291e3702589a5cd043acfded5e187f56ec765cc)) +* SSA parser ([#6489](https://github.com/noir-lang/noir/issues/6489)) ([21c9db5](https://github.com/noir-lang/noir/commit/21c9db5f325beef91df024838c4b33ff7f704332)) +* **ssa:** Unroll small loops in brillig ([#6505](https://github.com/noir-lang/noir/issues/6505)) ([5d5175e](https://github.com/noir-lang/noir/commit/5d5175e1c076bd651702b6c84a00c85bc4fea860)) +* Stop with HeapVector (https://github.com/AztecProtocol/aztec-packages/pull/9810) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9711) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) +* Use a full `BlackBoxFunctionSolver` implementation when execution brillig during acirgen ([#6481](https://github.com/noir-lang/noir/issues/6481)) ([22fc11a](https://github.com/noir-lang/noir/commit/22fc11ace31b515287f62219c0e6d6ed3d1bedd7)) + + +### Bug Fixes + +* Allow range checks to be performed within the comptime intepreter ([#6514](https://github.com/noir-lang/noir/issues/6514)) ([852c87a](https://github.com/noir-lang/noir/commit/852c87ae9ecdd441ee4c2ab3e78e86b2da07d8a4)) +* Disallow `#[test]` on associated functions ([#6449](https://github.com/noir-lang/noir/issues/6449)) ([35408ab](https://github.com/noir-lang/noir/commit/35408ab303f1018c1e2c38e6ea55430a2c89dc4c)) +* Do a shallow follow_bindings before unification ([#6558](https://github.com/noir-lang/noir/issues/6558)) ([32a9ed9](https://github.com/noir-lang/noir/commit/32a9ed9ad19cf81275c31ca77e4970bc1598c112)) +* **docs:** Fix broken links in oracles doc ([#6488](https://github.com/noir-lang/noir/issues/6488)) ([aa37cd5](https://github.com/noir-lang/noir/commit/aa37cd5be25412919f466a938260ae1a485ee096)) +* Fix poor handling of aliased references in flattening pass causing some values to be zeroed ([#6434](https://github.com/noir-lang/noir/issues/6434)) ([8932dac](https://github.com/noir-lang/noir/commit/8932dac4847c643341320c2893f7e4297c78c621)) +* Parse Slice type in SSa ([#6507](https://github.com/noir-lang/noir/issues/6507)) ([34ad666](https://github.com/noir-lang/noir/commit/34ad6669b210173ddf0484b04e47161b2cfbcadf)) +* Perform arithmetic simplification through `CheckedCast` ([#6502](https://github.com/noir-lang/noir/issues/6502)) ([72e8de0](https://github.com/noir-lang/noir/commit/72e8de0656c4789f57ff1d3ddecc8901df627aab)) +* Set local_module before elaborating each trait ([#6506](https://github.com/noir-lang/noir/issues/6506)) ([1df8c45](https://github.com/noir-lang/noir/commit/1df8c456d6d256f120d6df6ae3e6735cb7eb7dae)) +* Take blackbox function outputs into account when merging expressions ([#6532](https://github.com/noir-lang/noir/issues/6532)) ([713df69](https://github.com/noir-lang/noir/commit/713df69aad56fc5aaefd5d140275a3217de4d866)) +* **tests:** Use a file lock as well as a mutex to isolate tests cases ([#6508](https://github.com/noir-lang/noir/issues/6508)) ([cfc22cb](https://github.com/noir-lang/noir/commit/cfc22cb0ca133fce49a25c3f055f5a6b8bd9b58e)) +* Treat all parameters as possible aliases of each other ([#6477](https://github.com/noir-lang/noir/issues/6477)) ([0262e5b](https://github.com/noir-lang/noir/commit/0262e5b93ab71a420365c6e56d3250b2d1eea659)) +* Typing of artifacts (https://github.com/AztecProtocol/aztec-packages/pull/9581) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) + + +### Miscellaneous Chores + +* Remove `recursive` from ACIR format; add them to API and CLI (https://github.com/AztecProtocol/aztec-packages/pull/9479) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) + +## [0.38.0](https://github.com/noir-lang/noir/compare/v0.37.0...v0.38.0) (2024-11-08) + + +### ⚠ BREAKING CHANGES + +* Always Check Arithmetic Generics at Monomorphization ([#6329](https://github.com/noir-lang/noir/issues/6329)) + +### Features + +* Always Check Arithmetic Generics at Monomorphization ([#6329](https://github.com/noir-lang/noir/issues/6329)) ([2972db2](https://github.com/noir-lang/noir/commit/2972db20fc00ed0e43b662092f0d0712421d122f)) +* Ensure that generated ACIR is solvable ([#6415](https://github.com/noir-lang/noir/issues/6415)) ([b473d99](https://github.com/noir-lang/noir/commit/b473d99b2b70b595596b8392617256dbaf5d5642)) +* Nargo command to generate shell completions ([#6413](https://github.com/noir-lang/noir/issues/6413)) ([13856a1](https://github.com/noir-lang/noir/commit/13856a121125b1ccca15919942081a5d157d280e)) + + +### Bug Fixes + +* Check infix expression is valid in program input ([#6450](https://github.com/noir-lang/noir/issues/6450)) ([35dedb5](https://github.com/noir-lang/noir/commit/35dedb54a0853ba0fa85038d832a520f9ba01a98)) +* Discard optimisation that would change execution ordering or that is related to call outputs ([#6461](https://github.com/noir-lang/noir/issues/6461)) ([b8654f7](https://github.com/noir-lang/noir/commit/b8654f700b218cc09c5381af65df11ead9ffcdaf)) +* Don't crash on AsTraitPath with empty path ([#6454](https://github.com/noir-lang/noir/issues/6454)) ([fc72dcd](https://github.com/noir-lang/noir/commit/fc72dcdf3e8eeff73f72756e7ab87dddf2920657)) +* Fix Alias and Error kinds ([#6426](https://github.com/noir-lang/noir/issues/6426)) ([3cb259f](https://github.com/noir-lang/noir/commit/3cb259f419cf352f768728b15f849e520fc233cb)) +* Let formatter respect newlines between comments ([#6458](https://github.com/noir-lang/noir/issues/6458)) ([fb1a8ca](https://github.com/noir-lang/noir/commit/fb1a8ca67c58d87991358078e6c532b49824fdb8)) +* Right shift is not a regular division ([#6400](https://github.com/noir-lang/noir/issues/6400)) ([2247814](https://github.com/noir-lang/noir/commit/2247814f951f5d33257cd123a3bdcba857c9b167)) +* **sea:** Mem2reg to treat block input references as alias ([#6452](https://github.com/noir-lang/noir/issues/6452)) ([5310064](https://github.com/noir-lang/noir/commit/53100647bf1dc7917b66c9a7041c06b1e716fbe7)) +* **ssa:** Change array_set to not mutate slices coming from function inputs ([#6463](https://github.com/noir-lang/noir/issues/6463)) ([371bd45](https://github.com/noir-lang/noir/commit/371bd45130c9095e5dfb20dc79fbf41c02ed087c)) +* **ssa:** Resolve value IDs in terminator before comparing to array ([#6448](https://github.com/noir-lang/noir/issues/6448)) ([66f15ca](https://github.com/noir-lang/noir/commit/66f15caba8466501256a98cee289c49376b27097)) +* **tests:** Prevent EOF error while running test programs ([#6455](https://github.com/noir-lang/noir/issues/6455)) ([358e381](https://github.com/noir-lang/noir/commit/358e38107edbc4f40c97b88196456d82f5557e3f)) +* Type-check turbofish in trait before function call ([#6416](https://github.com/noir-lang/noir/issues/6416)) ([f8fd813](https://github.com/noir-lang/noir/commit/f8fd813b09ce870364700659e3ea8499ab51105e)) + +## [0.37.0](https://github.com/noir-lang/noir/compare/v0.36.0...v0.37.0) (2024-10-31) + + +### ⚠ BREAKING CHANGES + +* remove mimc from stdlib ([#6402](https://github.com/noir-lang/noir/issues/6402)) +* **avm/brillig:** revert/rethrow oracle (https://github.com/AztecProtocol/aztec-packages/pull/9408) +* use Brillig opcode when possible for less-than operations on fields (https://github.com/AztecProtocol/aztec-packages/pull/9416) +* remove noir_js_backend_barretenberg (https://github.com/AztecProtocol/aztec-packages/pull/9338) +* replace usage of vector in keccakf1600 input with array (https://github.com/AztecProtocol/aztec-packages/pull/9350) +* **profiler:** New flamegraph command that profiles the opcodes executed ([#6327](https://github.com/noir-lang/noir/issues/6327)) + +### Features + +* Add capacities to brillig vectors and use them in slice ops ([#6332](https://github.com/noir-lang/noir/issues/6332)) ([c9ff9a3](https://github.com/noir-lang/noir/commit/c9ff9a392f6142c04a3a512722ef6c9f9a7c3439)) +* **avm/brillig:** Revert/rethrow oracle (https://github.com/AztecProtocol/aztec-packages/pull/9408) ([321a493](https://github.com/noir-lang/noir/commit/321a493216e19a2f077007c3447a3030db0df0d0)) +* Better LSP hover for functions ([#6376](https://github.com/noir-lang/noir/issues/6376)) ([e92b519](https://github.com/noir-lang/noir/commit/e92b519bdfbd2a149a46745ad2ecffdd0e91f3f1)) +* Check trait where clause ([#6325](https://github.com/noir-lang/noir/issues/6325)) ([0de3241](https://github.com/noir-lang/noir/commit/0de3241bd290b1737ff831c30e5a2a0633a53eb3)) +* **ci:** Add report of Brillig opcodes executed ([#6396](https://github.com/noir-lang/noir/issues/6396)) ([e04b026](https://github.com/noir-lang/noir/commit/e04b02621e3651ddbb8e314563d614171a8a9933)) +* Do not increment reference counts on arrays through references ([#6375](https://github.com/noir-lang/noir/issues/6375)) ([60c770f](https://github.com/noir-lang/noir/commit/60c770f5f2594eea31ac75c852980edefa40d9eb)) +* Improve malformed test attribute error ([#6414](https://github.com/noir-lang/noir/issues/6414)) ([8f516d7](https://github.com/noir-lang/noir/commit/8f516d73d2d33988f6cdb9367244c11bc36ede22)) +* Let LSP suggest traits in trait bounds ([#6370](https://github.com/noir-lang/noir/issues/6370)) ([e909dcb](https://github.com/noir-lang/noir/commit/e909dcbb06c7b0043ffc79d5b8af99835b0096e5)) +* Let the formatter remove lambda block braces for single-statement blocks ([#6335](https://github.com/noir-lang/noir/issues/6335)) ([52f7c0b](https://github.com/noir-lang/noir/commit/52f7c0b67fa2f70848512c87fabcefc4c5426dd1)) +* Let the LSP import code action insert into existing use statements ([#6358](https://github.com/noir-lang/noir/issues/6358)) ([308717b](https://github.com/noir-lang/noir/commit/308717b6c44db4b206ad371cd6322478ce68746b)) +* LSP auto-import will try to add to existing use statements ([#6354](https://github.com/noir-lang/noir/issues/6354)) ([647f6a4](https://github.com/noir-lang/noir/commit/647f6a4bd3d00fd3b3b3e4ff17dce512287ee5b4)) +* Merge and sort imports ([#6322](https://github.com/noir-lang/noir/issues/6322)) ([07ab515](https://github.com/noir-lang/noir/commit/07ab5150857ec6719b132ec91d5f90af0564a046)) +* **perf:** Use [u32;16] for message block in sha256 ([#6324](https://github.com/noir-lang/noir/issues/6324)) ([81c612f](https://github.com/noir-lang/noir/commit/81c612f281cddf41d12ea62d9f610eab05ad1973)) +* **profiler:** Add Brillig procedure info to debug artifact for more informative profiling ([#6385](https://github.com/noir-lang/noir/issues/6385)) ([f5f65dc](https://github.com/noir-lang/noir/commit/f5f65dc29eb1f71926e6f8ed6681df563a85bd23)) +* **profiler:** New flamegraph command that profiles the opcodes executed ([#6327](https://github.com/noir-lang/noir/issues/6327)) ([4d87c9a](https://github.com/noir-lang/noir/commit/4d87c9ac78b48b4bd0ae81316df28aab390d004e)) +* Reject programs with unconditional recursion ([#6292](https://github.com/noir-lang/noir/issues/6292)) ([00c5c51](https://github.com/noir-lang/noir/commit/00c5c5154b818d0b50802721eae621efb3379a4e)) +* Remove 'single use' intermediate variables ([#6268](https://github.com/noir-lang/noir/issues/6268)) ([ec75e8e](https://github.com/noir-lang/noir/commit/ec75e8ec59e0f2a2169aea67372411ede4074d09)) +* Remove mimc from stdlib ([#6402](https://github.com/noir-lang/noir/issues/6402)) ([ec03e77](https://github.com/noir-lang/noir/commit/ec03e779f438069e51e973d8f29727e1e0fb5665)) +* Sha256 refactoring and benchmark with longer input ([#6318](https://github.com/noir-lang/noir/issues/6318)) ([d606491](https://github.com/noir-lang/noir/commit/d606491a61a9fe2153666f7d0a3ec6cae7bfaecb)) +* **ssa:** Various mem2reg reverts to reduce memory and compilation time ([#6307](https://github.com/noir-lang/noir/issues/6307)) ([b820328](https://github.com/noir-lang/noir/commit/b82032888819eac82b2bfce8300c2c8b66507c64)) +* Suggest removing `!` from macro call that doesn't return Quoted ([#6384](https://github.com/noir-lang/noir/issues/6384)) ([0232b57](https://github.com/noir-lang/noir/commit/0232b573c418ab74715b7cc1d3e858d993bc1c07)) +* Support specifying generics on a struct when calling an associated function ([#6306](https://github.com/noir-lang/noir/issues/6306)) ([eba151e](https://github.com/noir-lang/noir/commit/eba151ecf59c61f7ffc6bec00d455dce84e7b927)) +* **test:** Run test matrix on stdlib tests ([#6352](https://github.com/noir-lang/noir/issues/6352)) ([4c39514](https://github.com/noir-lang/noir/commit/4c39514fccf3595de6bdfad755b6ae2d3ef11aa1)) + + +### Bug Fixes + +* (formatter) correctly format quote delimiters ([#6377](https://github.com/noir-lang/noir/issues/6377)) ([b42accf](https://github.com/noir-lang/noir/commit/b42accf59c9294131ce2773ac3ebdb20f548ece5)) +* (formatter) indent after infix lhs ([#6331](https://github.com/noir-lang/noir/issues/6331)) ([c891ffd](https://github.com/noir-lang/noir/commit/c891ffda9df17eabcaf2035f098d29f97bfc463a)) +* (LSP) check visibility of module that re-exports item, if any ([#6371](https://github.com/noir-lang/noir/issues/6371)) ([a4fc6e8](https://github.com/noir-lang/noir/commit/a4fc6e861492ab5ff12ebc5fdbb248f983eab0a2)) +* Aliases in path ([#6399](https://github.com/noir-lang/noir/issues/6399)) ([be882f1](https://github.com/noir-lang/noir/commit/be882f11ee661bf19ed6d78a7b3085099d4273e8)) +* Allow globals in format strings ([#6382](https://github.com/noir-lang/noir/issues/6382)) ([15c729a](https://github.com/noir-lang/noir/commit/15c729a7f29564092411658be613145b18ddd226)) +* Allow type aliases in let patterns ([#6356](https://github.com/noir-lang/noir/issues/6356)) ([91c0842](https://github.com/noir-lang/noir/commit/91c08421fdc5df7edcf502fb7fc1d343bb860b03)) +* Always inline `derive_generators` ([#6350](https://github.com/noir-lang/noir/issues/6350)) ([7c98b36](https://github.com/noir-lang/noir/commit/7c98b36305ffdbbaee3947723f248fa718e7a950)) +* Better formatting of leading/trailing line/block comments in expression lists ([#6338](https://github.com/noir-lang/noir/issues/6338)) ([3299c25](https://github.com/noir-lang/noir/commit/3299c25cefb6e3eb4b55396b2f842138b658e42f)) +* Display every bit in integer tokens ([#6360](https://github.com/noir-lang/noir/issues/6360)) ([b985fdf](https://github.com/noir-lang/noir/commit/b985fdf6e635570b8db3af83d9ec14e7cd749062)) +* Distinguish TypePath with and without turbofish ([#6404](https://github.com/noir-lang/noir/issues/6404)) ([0e974c2](https://github.com/noir-lang/noir/commit/0e974c22a1de0f6d38bc7a59280f86222f864698)) +* Fix panic in comptime code ([#6361](https://github.com/noir-lang/noir/issues/6361)) ([2f37610](https://github.com/noir-lang/noir/commit/2f376100d3ee7ab519d6ea30153395bb3e7af7b1)) +* Formatter didn't format `>>=` well ([#6337](https://github.com/noir-lang/noir/issues/6337)) ([598230d](https://github.com/noir-lang/noir/commit/598230d9427cf988fc6da8fe9e1eb2b7c00a2fa6)) +* LSP auto-import would import public item inside private module ([#6366](https://github.com/noir-lang/noir/issues/6366)) ([51eb295](https://github.com/noir-lang/noir/commit/51eb2954e8dfb3da298431a82f36fa72ebbee8eb)) +* Make keccak256 work with input lengths greater than 136 bytes ([#6393](https://github.com/noir-lang/noir/issues/6393)) ([07c9322](https://github.com/noir-lang/noir/commit/07c9322332e147c0e8fade5e238552ecbf3e7849)) +* Mutable global pattern didn't have a span ([#6328](https://github.com/noir-lang/noir/issues/6328)) ([5a6dae9](https://github.com/noir-lang/noir/commit/5a6dae9a9ee9c3650695a16d18fb8b7ac12180f4)) +* Numeric generic doesn't have a default type ([#6405](https://github.com/noir-lang/noir/issues/6405)) ([3a073f7](https://github.com/noir-lang/noir/commit/3a073f7446e3cd78ca963b221e05f341a6041067)) +* Remove assumed parent traits ([#6365](https://github.com/noir-lang/noir/issues/6365)) ([83d29f2](https://github.com/noir-lang/noir/commit/83d29f259debe41d0b5cdfb6e63d31733ae4e0c7)) +* Slightly better formatting of empty blocks with comments ([#6367](https://github.com/noir-lang/noir/issues/6367)) ([da72979](https://github.com/noir-lang/noir/commit/da729791b7ffcfcd2f58ba1f8bf2c274c04f303e)) +* **ssa:** Do not mark an array from a parameter mutable ([#6355](https://github.com/noir-lang/noir/issues/6355)) ([bcd8976](https://github.com/noir-lang/noir/commit/bcd897627c69b1ebcadc8b84abe2922ce3473c56)) + + +### Miscellaneous Chores + +* Remove noir_js_backend_barretenberg (https://github.com/AztecProtocol/aztec-packages/pull/9338) ([3925228](https://github.com/noir-lang/noir/commit/392522880e102e275ebcf42f16651a8ffa0bbbd2)) +* Replace usage of vector in keccakf1600 input with array (https://github.com/AztecProtocol/aztec-packages/pull/9350) ([3925228](https://github.com/noir-lang/noir/commit/392522880e102e275ebcf42f16651a8ffa0bbbd2)) +* Use Brillig opcode when possible for less-than operations on fields (https://github.com/AztecProtocol/aztec-packages/pull/9416) ([321a493](https://github.com/noir-lang/noir/commit/321a493216e19a2f077007c3447a3030db0df0d0)) + +## [0.36.0](https://github.com/noir-lang/noir/compare/v0.35.0...v0.36.0) (2024-10-22) + + +### ⚠ BREAKING CHANGES + +* remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) +* remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) +* remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) +* **avm:** remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) +* Integer division is not the inverse of integer multiplication ([#6243](https://github.com/noir-lang/noir/issues/6243)) +* kind size checks ([#6137](https://github.com/noir-lang/noir/issues/6137)) +* Change tag attributes to require a ' prefix ([#6235](https://github.com/noir-lang/noir/issues/6235)) + +### Features + +* Add `checked_transmute` ([#6262](https://github.com/noir-lang/noir/issues/6262)) ([2618061](https://github.com/noir-lang/noir/commit/2618061ee88e47fb063904d50af7a4eea26d3db9)) +* Add more `Type` and `UnresolvedType` methods ([#5994](https://github.com/noir-lang/noir/issues/5994)) ([8236cbd](https://github.com/noir-lang/noir/commit/8236cbdff60c1aaf41fc53142b6f0f9ea2fc2fa8)) +* Allow `unconstrained` after visibility ([#6246](https://github.com/noir-lang/noir/issues/6246)) ([f6dfbcf](https://github.com/noir-lang/noir/commit/f6dfbcf057efc95141b36499152dbd0b919a31b3)) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Don't crash LSP when there are errors resolving the workspace ([#6257](https://github.com/noir-lang/noir/issues/6257)) ([7cc7197](https://github.com/noir-lang/noir/commit/7cc7197bf7b2e41c07e8d1979f7e9d45c676d11b)) +* Don't suggest private struct fields in LSP ([#6256](https://github.com/noir-lang/noir/issues/6256)) ([2a727b3](https://github.com/noir-lang/noir/commit/2a727b3f7f7fb84ab88b0d08e1ab29ae012a8c4f)) +* Handwritten parser ([#6180](https://github.com/noir-lang/noir/issues/6180)) ([c4273a0](https://github.com/noir-lang/noir/commit/c4273a0c8f8b751a3dbe097e070e4e7b2c8ec438)) +* **improve:** Remove scan through globals ([#6282](https://github.com/noir-lang/noir/issues/6282)) ([fd91913](https://github.com/noir-lang/noir/commit/fd91913806a49255ba721012c2e302959a82c4f6)) +* Inclusive for loop ([#6200](https://github.com/noir-lang/noir/issues/6200)) ([bd861f2](https://github.com/noir-lang/noir/commit/bd861f282144056ecb52954fa9f6fd8db918e093)) +* Integrate databus in the private kernels (https://github.com/AztecProtocol/aztec-packages/pull/9028) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* **interpreter:** Comptime derive generators ([#6303](https://github.com/noir-lang/noir/issues/6303)) ([d8767b3](https://github.com/noir-lang/noir/commit/d8767b364f4db9a52c823e7f39f36feac3c90fcd)) +* Kind size checks ([#6137](https://github.com/noir-lang/noir/issues/6137)) ([6e40f62](https://github.com/noir-lang/noir/commit/6e40f628a87ab4b5e9e817b7b3a790920dc01683)) +* New formatter ([#6300](https://github.com/noir-lang/noir/issues/6300)) ([62404d7](https://github.com/noir-lang/noir/commit/62404d7ff349ddf7551f2efd865adafc5213a742)) +* Optimize `Quoted::as_expr` by parsing just once ([#6237](https://github.com/noir-lang/noir/issues/6237)) ([a4fcd00](https://github.com/noir-lang/noir/commit/a4fcd0017e019f05b5a4d6b97c50b75f9e560210)) +* Optimize reading a workspace's files ([#6281](https://github.com/noir-lang/noir/issues/6281)) ([b54ed26](https://github.com/noir-lang/noir/commit/b54ed2671c8bc0e198e262883598936b9e49d69e)) +* **perf:** Flamegraphs for test program execution benchmarks ([#6253](https://github.com/noir-lang/noir/issues/6253)) ([c186791](https://github.com/noir-lang/noir/commit/c186791636c2afb2d3763bccee956298039feed2)) +* **perf:** Follow array sets backwards in array set from get optimization ([#6208](https://github.com/noir-lang/noir/issues/6208)) ([999071b](https://github.com/noir-lang/noir/commit/999071b80e61a37cb994a4e359eabbac27cd53f1)) +* Recover from '=' instead of ':' in struct constructor/pattern ([#6236](https://github.com/noir-lang/noir/issues/6236)) ([9a12f31](https://github.com/noir-lang/noir/commit/9a12f31e909bbd4d4f0538704b3f40ea654fabaf)) +* Remove byte decomposition in `compute_decomposition` ([#6159](https://github.com/noir-lang/noir/issues/6159)) ([a8bcae2](https://github.com/noir-lang/noir/commit/a8bcae215bf19356226ad052710c94b64da90ffa)) +* Show LSP diagnostic related information ([#6277](https://github.com/noir-lang/noir/issues/6277)) ([c8a91a5](https://github.com/noir-lang/noir/commit/c8a91a55d69c54e3ea9b6a16053fa83ce17b1426)) +* Slightly improve "unexpected token" error message ([#6279](https://github.com/noir-lang/noir/issues/6279)) ([8232bfa](https://github.com/noir-lang/noir/commit/8232bfaf0a88dcba5a6949489b81d78c3413c5bc)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8934) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9034) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9099) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9275) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* **test:** Fuzz poseidon hases against an external library ([#6273](https://github.com/noir-lang/noir/issues/6273)) ([8d8ea89](https://github.com/noir-lang/noir/commit/8d8ea8963c5e4e23bd387aa729e09d3a9553a698)) +* **test:** Fuzz test poseidon2 hash equivalence ([#6265](https://github.com/noir-lang/noir/issues/6265)) ([f61ba03](https://github.com/noir-lang/noir/commit/f61ba037c6726e19be4f894d9447fe396df95417)) +* **test:** Fuzz test stdlib hash functions ([#6233](https://github.com/noir-lang/noir/issues/6233)) ([1a2ca46](https://github.com/noir-lang/noir/commit/1a2ca46af0d1c05813dbe28670a2bc39b79e4c9f)) +* **test:** Include the PoseidonHasher in the fuzzing ([#6280](https://github.com/noir-lang/noir/issues/6280)) ([afb8a7c](https://github.com/noir-lang/noir/commit/afb8a7cf7b1751a10dd2cdd87817945fa4c1ed1f)) +* Trait inheritance ([#6252](https://github.com/noir-lang/noir/issues/6252)) ([d3301a4](https://github.com/noir-lang/noir/commit/d3301a4f5558cf4e173f7d0edc08186ad4fb2eee)) +* Visibility for impl functions ([#6179](https://github.com/noir-lang/noir/issues/6179)) ([1b26440](https://github.com/noir-lang/noir/commit/1b26440889379f491315cd9d088537b1898d57c5)) +* Visibility for struct fields ([#6221](https://github.com/noir-lang/noir/issues/6221)) ([fc1c7ab](https://github.com/noir-lang/noir/commit/fc1c7ab6ee7be7c9d57fab5b2efe252c613f326b)) +* Warn about private types leaking in public functions and struct fields ([#6296](https://github.com/noir-lang/noir/issues/6296)) ([67ac0d6](https://github.com/noir-lang/noir/commit/67ac0d60c3e8b450a9e871f3edb29322ac5045d2)) + + +### Bug Fixes + +* Add missing visibility for auto-import names ([#6205](https://github.com/noir-lang/noir/issues/6205)) ([c3cb38a](https://github.com/noir-lang/noir/commit/c3cb38a7c4de6fc321b367eda3fca6d06e76b77a)) +* Address inactive public key check in `verify_signature_noir` ([#6270](https://github.com/noir-lang/noir/issues/6270)) ([e4325aa](https://github.com/noir-lang/noir/commit/e4325aace424d5c4552c92cdb360974fdd294048)) +* Allow array map on empty arrays ([#6305](https://github.com/noir-lang/noir/issues/6305)) ([51ae1b3](https://github.com/noir-lang/noir/commit/51ae1b324cd73fdb4fe3695b5d483a44b4aff4a9)) +* Change tag attributes to require a ' prefix ([#6235](https://github.com/noir-lang/noir/issues/6235)) ([b43dcb2](https://github.com/noir-lang/noir/commit/b43dcb2b30ce090c393990b2192411f9b3dc6a9e)) +* Check for Schnorr null signature ([#6226](https://github.com/noir-lang/noir/issues/6226)) ([2430920](https://github.com/noir-lang/noir/commit/24309200f600ad20a51d9f2c6c53849466fccda4)) +* Display function name and body when inlining recursion limit hit ([#6291](https://github.com/noir-lang/noir/issues/6291)) ([33a1e7d](https://github.com/noir-lang/noir/commit/33a1e7d2246bdea48dd6fe925d427c7be8c4659d)) +* Do not warn on unused self in traits ([#6298](https://github.com/noir-lang/noir/issues/6298)) ([4d524bf](https://github.com/noir-lang/noir/commit/4d524bf34de98449419a025aa53d593bf42e70a7)) +* Don't warn on unuse global if it has an abi annotation ([#6258](https://github.com/noir-lang/noir/issues/6258)) ([e13f617](https://github.com/noir-lang/noir/commit/e13f61741d17ed2e03ff26cb858cb3d243e67c88)) +* Don't warn on unused struct that has an abi annotation ([#6254](https://github.com/noir-lang/noir/issues/6254)) ([8a31632](https://github.com/noir-lang/noir/commit/8a316324a971a10d46392d7c64125d1d6ac9d557)) +* Don't warn twice when referring to private item ([#6216](https://github.com/noir-lang/noir/issues/6216)) ([619c545](https://github.com/noir-lang/noir/commit/619c5451b152d62e01d3c4c1da7e13ff6502f915)) +* Enforce correctness of decompositions performed at compile time ([#6278](https://github.com/noir-lang/noir/issues/6278)) ([53252fd](https://github.com/noir-lang/noir/commit/53252fd521ce7818a1d97824be30466590d879f5)) +* **frontend:** Do not warn when a nested struct is provided as input to main ([#6239](https://github.com/noir-lang/noir/issues/6239)) ([9dfe223](https://github.com/noir-lang/noir/commit/9dfe223e4dc168351c5cceb9d1abda326141b014)) +* Handle dfg databus in SSA normalization ([#6249](https://github.com/noir-lang/noir/issues/6249)) ([9d8bee5](https://github.com/noir-lang/noir/commit/9d8bee5b4e9308a812b1f93c3a48ddd11971ac17)) +* Handle nested arrays in calldata ([#6232](https://github.com/noir-lang/noir/issues/6232)) ([0ab8f5e](https://github.com/noir-lang/noir/commit/0ab8f5e3c32af05a3c158562c0fcf9729741e0ab)) +* Homogeneous input points for EC ADD ([#6241](https://github.com/noir-lang/noir/issues/6241)) ([f6a7306](https://github.com/noir-lang/noir/commit/f6a7306436ea1a37ec7f3b884721b50467e9a063)) +* Integer division is not the inverse of integer multiplication ([#6243](https://github.com/noir-lang/noir/issues/6243)) ([1cd2587](https://github.com/noir-lang/noir/commit/1cd2587bf67143832f76f90c25aecca1a46b1284)) +* Panic on composite types within databus ([#6225](https://github.com/noir-lang/noir/issues/6225)) ([29bd125](https://github.com/noir-lang/noir/commit/29bd125314b58e2eac23742ff1de022a97dcc60a)) +* Prevent compiler panic when popping from empty slices ([#6274](https://github.com/noir-lang/noir/issues/6274)) ([87137d8](https://github.com/noir-lang/noir/commit/87137d8d93622052dbe1c8a933d542a5c147c15c)) +* Reject invalid expression with in CLI parser ([#6287](https://github.com/noir-lang/noir/issues/6287)) ([052aee8](https://github.com/noir-lang/noir/commit/052aee80ff3e1e4fd2ca45310d7bb8b980af126a)) +* Remove need for duplicate attributes on each function (https://github.com/AztecProtocol/aztec-packages/pull/9244) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Visibility for impl methods ([#6261](https://github.com/noir-lang/noir/issues/6261)) ([70cbeb4](https://github.com/noir-lang/noir/commit/70cbeb4322a0b11c1c167ab27bf0408d04fe7b7d)) + + +### Miscellaneous Chores + +* Remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) + + +### Code Refactoring + +* **avm:** Remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) + +## [0.35.0](https://github.com/noir-lang/noir/compare/v0.34.0...v0.35.0) (2024-10-03) + + +### ⚠ BREAKING CHANGES + +* Syncing TypeVariableKind with Kind ([#6094](https://github.com/noir-lang/noir/issues/6094)) +* remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) +* add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) +* Infer globals to be u32 when used in a type ([#6083](https://github.com/noir-lang/noir/issues/6083)) +* removing implicit numeric generics ([#5837](https://github.com/noir-lang/noir/issues/5837)) + +### Features + +* (LSP) if in runtime code, always suggest functions that return Quoted as macro calls ([#6098](https://github.com/noir-lang/noir/issues/6098)) ([4a160cb](https://github.com/noir-lang/noir/commit/4a160cb99cbd9928c034a7009f398974fc6fdb11)) +* (LSP) remove unused imports ([#6129](https://github.com/noir-lang/noir/issues/6129)) ([98bc460](https://github.com/noir-lang/noir/commit/98bc46002cdd8daff1baf0756ecc60dbdf420fd9)) +* (LSP) show global value on hover ([#6097](https://github.com/noir-lang/noir/issues/6097)) ([3d9d072](https://github.com/noir-lang/noir/commit/3d9d07210544c9d27051eb5e629585760f48cd1c)) +* (LSP) suggest $vars inside `quote { ... }` ([#6114](https://github.com/noir-lang/noir/issues/6114)) ([73245b3](https://github.com/noir-lang/noir/commit/73245b3aae0c65780a102ac6842f06df65e5fc35)) +* Add `Expr::as_constructor` ([#5980](https://github.com/noir-lang/noir/issues/5980)) ([76dea7b](https://github.com/noir-lang/noir/commit/76dea7b409baa98236f6433f17c2ce9206dd4ba3)) +* Add `Expr::as_for` and `Expr::as_for_range` ([#6039](https://github.com/noir-lang/noir/issues/6039)) ([abcae75](https://github.com/noir-lang/noir/commit/abcae750f022dd7c49cee616edddd7b1cc93f3b8)) +* Add `Expr::as_lambda` ([#6048](https://github.com/noir-lang/noir/issues/6048)) ([31130dc](https://github.com/noir-lang/noir/commit/31130dc7aec24a7a7b9f342df94b14f295eb2103)) +* Add a `comptime` string type for string handling at compile-time ([#6026](https://github.com/noir-lang/noir/issues/6026)) ([5d2984f](https://github.com/noir-lang/noir/commit/5d2984fce4f55e43cb418e40462d430227b71768)) +* Add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Allow silencing an unused variable defined via `let` ([#6149](https://github.com/noir-lang/noir/issues/6149)) ([a2bc059](https://github.com/noir-lang/noir/commit/a2bc059f993d3e9ca06a2fe4857ef1c522c97286)) +* Allow visibility modifiers in struct definitions ([#6054](https://github.com/noir-lang/noir/issues/6054)) ([199be58](https://github.com/noir-lang/noir/commit/199be584a36d20660ada49473050c5191251d6c5)) +* Check unconstrained trait impl method matches ([#6057](https://github.com/noir-lang/noir/issues/6057)) ([aedc983](https://github.com/noir-lang/noir/commit/aedc9832240e55473c504fa2e6e3b3af618bda08)) +* Default to outputting witness with file named after package ([#6031](https://github.com/noir-lang/noir/issues/6031)) ([e74b4ae](https://github.com/noir-lang/noir/commit/e74b4ae3ebcf301eedc5d0059bcebd5dced75d72)) +* Detect unconstructed structs ([#6061](https://github.com/noir-lang/noir/issues/6061)) ([bcb438b](https://github.com/noir-lang/noir/commit/bcb438b0816fbe08344535545612d32b4730af79)) +* Do not double error on import with error ([#6131](https://github.com/noir-lang/noir/issues/6131)) ([9b26650](https://github.com/noir-lang/noir/commit/9b26650f4a45c220484fc187500c7307af9c88d7)) +* Expose `derived_generators` and `pedersen_commitment_with_separator` from the stdlib ([#6154](https://github.com/noir-lang/noir/issues/6154)) ([877b806](https://github.com/noir-lang/noir/commit/877b806ee02cb640472c6bb2b1ed7bc76b861a9b)) +* Faster LSP by caching file managers ([#6047](https://github.com/noir-lang/noir/issues/6047)) ([c48a4f8](https://github.com/noir-lang/noir/commit/c48a4f83063ff55574d5b4a6277950a9edbc6317)) +* Hoist constant allocation outside of loops ([#6158](https://github.com/noir-lang/noir/issues/6158)) ([180bfc9](https://github.com/noir-lang/noir/commit/180bfc99944cd42b3f44048213458d1399687cef)) +* Implement `to_be_radix` in the comptime interpreter ([#6043](https://github.com/noir-lang/noir/issues/6043)) ([1550278](https://github.com/noir-lang/noir/commit/1550278f1e96392967b477b9b12be3bb0eea8fd6)) +* Implement solver for mov_registers_to_registers ([#6089](https://github.com/noir-lang/noir/issues/6089)) ([4170c55](https://github.com/noir-lang/noir/commit/4170c55019bd27fd51be8a46637514dfe86de53c)) +* Implement type paths ([#6093](https://github.com/noir-lang/noir/issues/6093)) ([2174ffb](https://github.com/noir-lang/noir/commit/2174ffb92b5d88e7e0926c91f42bc7f849e8ddc1)) +* Let `Module::functions` and `Module::structs` return them in definition order ([#6178](https://github.com/noir-lang/noir/issues/6178)) ([dec9874](https://github.com/noir-lang/noir/commit/dec98747197442f6c2a15e6543c5d453dff4b967)) +* Let LSP suggest macro calls too ([#6090](https://github.com/noir-lang/noir/issues/6090)) ([26d275b](https://github.com/noir-lang/noir/commit/26d275b65fa339d877c90d5c6c13ac8ef47189e1)) +* Let LSP suggest trait impl methods as you are typing them ([#6029](https://github.com/noir-lang/noir/issues/6029)) ([dfed81b](https://github.com/noir-lang/noir/commit/dfed81b4b39b2f783d6e81a78ee27fba7032e01c)) +* LSP autocompletion for `TypePath` ([#6117](https://github.com/noir-lang/noir/issues/6117)) ([3f79d8f](https://github.com/noir-lang/noir/commit/3f79d8f04c5f90c6b21359a3d0960446ebf84b2d)) +* **metaprogramming:** Add `#[use_callers_scope]` ([#6050](https://github.com/noir-lang/noir/issues/6050)) ([8c34046](https://github.com/noir-lang/noir/commit/8c340461c3f7054839009c4b1ed5ac8a0dd55e09)) +* Optimize allocating immediate amounts of memory (https://github.com/AztecProtocol/aztec-packages/pull/8579) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Optimize constraints in sha256 ([#6145](https://github.com/noir-lang/noir/issues/6145)) ([164d29e](https://github.com/noir-lang/noir/commit/164d29e4d1960d16fdeafe2cc8ea8144a769f7b2)) +* **perf:** Allow array set last uses optimization in return block of Brillig functions ([#6119](https://github.com/noir-lang/noir/issues/6119)) ([5598059](https://github.com/noir-lang/noir/commit/5598059576c6cbc72474aff4b18bc5e4bb9f08e1)) +* **perf:** Handle array set optimization across blocks for Brillig functions ([#6153](https://github.com/noir-lang/noir/issues/6153)) ([12cb80a](https://github.com/noir-lang/noir/commit/12cb80a214fd81eb7619413a6d0663369be38512)) +* **perf:** Optimize array set from get ([#6207](https://github.com/noir-lang/noir/issues/6207)) ([dfeb1c5](https://github.com/noir-lang/noir/commit/dfeb1c51c564ec345978a9a0efef3e4e96ab638a)) +* **perf:** Remove inc_rc instructions for arrays which are never mutably borrowed ([#6168](https://github.com/noir-lang/noir/issues/6168)) ([a195442](https://github.com/noir-lang/noir/commit/a19544247fffaf5d2fe0d6d45013f833576f7c61)) +* **perf:** Remove redundant inc rc without instructions between ([#6183](https://github.com/noir-lang/noir/issues/6183)) ([be9dcfe](https://github.com/noir-lang/noir/commit/be9dcfe56d808b1bd5ef552d41274705b2df7062)) +* **perf:** Remove unused loads in mem2reg and last stores per function ([#5925](https://github.com/noir-lang/noir/issues/5925)) ([19eef30](https://github.com/noir-lang/noir/commit/19eef30cdbd8a3a4671aabbbe66b5481a5dec3f7)) +* **perf:** Remove useless paired RC instructions within a block during DIE ([#6160](https://github.com/noir-lang/noir/issues/6160)) ([59c4118](https://github.com/noir-lang/noir/commit/59c41182faa19d1cb8c9be5c11d50636fc17dad7)) +* **perf:** Simplify the cfg after DIE ([#6184](https://github.com/noir-lang/noir/issues/6184)) ([a1b5046](https://github.com/noir-lang/noir/commit/a1b50466bfd8c44d50440e00ecb50e29425471e5)) +* Pretty print Quoted token stream ([#6111](https://github.com/noir-lang/noir/issues/6111)) ([cd81f85](https://github.com/noir-lang/noir/commit/cd81f85856a477e208533ebd0915b5901c1bb184)) +* Refactor SSA passes to run on individual functions ([#6072](https://github.com/noir-lang/noir/issues/6072)) ([85c502c](https://github.com/noir-lang/noir/commit/85c502c9fa69b151fdff1a97b5a97ad78cb599ab)) +* Remove aztec macros ([#6087](https://github.com/noir-lang/noir/issues/6087)) ([9d96207](https://github.com/noir-lang/noir/commit/9d962077630131840f0cb7c211f462b579b0b577)) +* Remove orphaned blocks from cfg to improve `simplify_cfg` pass. ([#6198](https://github.com/noir-lang/noir/issues/6198)) ([b4712c5](https://github.com/noir-lang/noir/commit/b4712c5ba50ef38789978522afcd251ffbcf8780)) +* Remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Remove unnecessary branching in keccak impl ([#6133](https://github.com/noir-lang/noir/issues/6133)) ([9c69dce](https://github.com/noir-lang/noir/commit/9c69dce2250b6fc656af8d9c06d7fac34b35c73a)) +* Represent assertions more similarly to function calls ([#6103](https://github.com/noir-lang/noir/issues/6103)) ([3ecd0e2](https://github.com/noir-lang/noir/commit/3ecd0e29441d27bc77c49993495209a70be0d86e)) +* Show test output when running via LSP ([#6049](https://github.com/noir-lang/noir/issues/6049)) ([9fb010e](https://github.com/noir-lang/noir/commit/9fb010ef8a93cf25e4d361ee42aa8969e5a46bab)) +* Simplify sha256 implementation ([#6142](https://github.com/noir-lang/noir/issues/6142)) ([acdfbbc](https://github.com/noir-lang/noir/commit/acdfbbc4ecc9d213dc885a12952e29e188420dff)) +* Skip `remove_enable_side_effects` pass on brillig functions ([#6199](https://github.com/noir-lang/noir/issues/6199)) ([2303615](https://github.com/noir-lang/noir/commit/2303615815a2a60de8ac3dd53349f85201660917)) +* **ssa:** Simplify signed casts ([#6166](https://github.com/noir-lang/noir/issues/6166)) ([eec3a61](https://github.com/noir-lang/noir/commit/eec3a6152493e56866ec5338ff52f823c530778e)) +* Swap endianness in-place in keccak implementation ([#6128](https://github.com/noir-lang/noir/issues/6128)) ([e3cdebe](https://github.com/noir-lang/noir/commit/e3cdebe515e4dc4ee6e16e01bd8af25135939798)) +* Syncing TypeVariableKind with Kind ([#6094](https://github.com/noir-lang/noir/issues/6094)) ([6440e18](https://github.com/noir-lang/noir/commit/6440e183085160d77563b4e735ccaaf199e21693)) +* Visibility for globals ([#6161](https://github.com/noir-lang/noir/issues/6161)) ([103b54d](https://github.com/noir-lang/noir/commit/103b54db8a5a81ecf76381fe99320c1e1f606898)) +* Visibility for modules ([#6165](https://github.com/noir-lang/noir/issues/6165)) ([fcdbcb9](https://github.com/noir-lang/noir/commit/fcdbcb91afb18771cbb5ee48628e171845f22f5f)) +* Visibility for traits ([#6056](https://github.com/noir-lang/noir/issues/6056)) ([5bbd9ba](https://github.com/noir-lang/noir/commit/5bbd9ba9a6d6494fd16813b44036b78c871f6613)) +* Visibility for type aliases ([#6058](https://github.com/noir-lang/noir/issues/6058)) ([66d2a07](https://github.com/noir-lang/noir/commit/66d2a07f0fedb04422c218cbe8d6fb080efac994)) + + +### Bug Fixes + +* (LSP) make goto and hover work well for attributes ([#6152](https://github.com/noir-lang/noir/issues/6152)) ([c679bc6](https://github.com/noir-lang/noir/commit/c679bc6bbd291b6264820dd497b37279116a1cd2)) +* Allow macros to change types on each iteration of a comptime loop ([#6105](https://github.com/noir-lang/noir/issues/6105)) ([0864e7c](https://github.com/noir-lang/noir/commit/0864e7c945089cc06f8cc9e5c7d933c465d8c892)) +* Allow providing default implementations of unconstrained trait methods ([#6138](https://github.com/noir-lang/noir/issues/6138)) ([7679bbc](https://github.com/noir-lang/noir/commit/7679bbc10cb2fa480489fe1aad83fe77ec2af7e8)) +* Always parse all tokens from quoted token streams ([#6064](https://github.com/noir-lang/noir/issues/6064)) ([23ed74b](https://github.com/noir-lang/noir/commit/23ed74bc94ec4da8dbd35da0ae39b26c7ef601e5)) +* Be more lenient with semicolons on interned expressions ([#6062](https://github.com/noir-lang/noir/issues/6062)) ([052c4fe](https://github.com/noir-lang/noir/commit/052c4fe52a4df9d6492f9b0d6b449151b87b18d5)) +* Consider constants as used values to keep their rc ops ([#6122](https://github.com/noir-lang/noir/issues/6122)) ([1217005](https://github.com/noir-lang/noir/commit/12170056102ea15698aacc820876fee0bb7d0c68)) +* Correct stack trace order in comptime assertion failures ([#6066](https://github.com/noir-lang/noir/issues/6066)) ([04f1636](https://github.com/noir-lang/noir/commit/04f1636ca0ccd741c72fa98d6c26227ea9835b0c)) +* Databus panic for fns with empty params (https://github.com/AztecProtocol/aztec-packages/pull/8847) ([d252748](https://github.com/noir-lang/noir/commit/d2527482dafef694be2f389e5b4dbc813234da71)) +* Decode databus return values ([#6095](https://github.com/noir-lang/noir/issues/6095)) ([c40eb1f](https://github.com/noir-lang/noir/commit/c40eb1fd8a0ba63b2d122e42b47dfa9dca5bf7b0)) +* Disable side-effects for no_predicates functions ([#6027](https://github.com/noir-lang/noir/issues/6027)) ([fc74c55](https://github.com/noir-lang/noir/commit/fc74c55ffed892962413c6fe15af62e1d2e7b785)) +* Disambiguate field or int static trait method call ([#6112](https://github.com/noir-lang/noir/issues/6112)) ([5b27ea4](https://github.com/noir-lang/noir/commit/5b27ea4d8031318723cc2b97f76758d401a565a0)) +* Do not duplicate constant arrays in brillig ([#6155](https://github.com/noir-lang/noir/issues/6155)) ([68f3022](https://github.com/noir-lang/noir/commit/68f3022fcdaab6e379e43091b3242e6ea51cff26)) +* **docs:** Rename recursion.md to recursion.mdx ([#6195](https://github.com/noir-lang/noir/issues/6195)) ([054e48b](https://github.com/noir-lang/noir/commit/054e48b76e7b083feb500d30c54912f9db57c565)) +* Don't crash on untyped global used as array length ([#6076](https://github.com/noir-lang/noir/issues/6076)) ([426f295](https://github.com/noir-lang/noir/commit/426f2955cbe4f086581d05eea7d06c47e0491195)) +* Ensure to_bytes returns the canonical decomposition ([#6084](https://github.com/noir-lang/noir/issues/6084)) ([b280a79](https://github.com/noir-lang/noir/commit/b280a79cf8a4fd2a97200e5436e0ec7cb7134711)) +* Error on `&mut x` when `x` is not mutable ([#6037](https://github.com/noir-lang/noir/issues/6037)) ([57afc7d](https://github.com/noir-lang/noir/commit/57afc7ddd424220106af7b9c6e0715007f6ea8b8)) +* Fix canonicalization bug ([#6033](https://github.com/noir-lang/noir/issues/6033)) ([7397772](https://github.com/noir-lang/noir/commit/739777214863de4088162711953f26ca992b356e)) +* Fix comptime type formatting ([#6079](https://github.com/noir-lang/noir/issues/6079)) ([e678091](https://github.com/noir-lang/noir/commit/e67809165c277423e25110c3f1f8eff6e8daa0e4)) +* Handle multi-byte utf8 characters in formatter ([#6118](https://github.com/noir-lang/noir/issues/6118)) ([b1d0619](https://github.com/noir-lang/noir/commit/b1d061926376965805ef3ece3e32d94df81462a6)) +* Handle parenthesized expressions in array length ([#6132](https://github.com/noir-lang/noir/issues/6132)) ([9f0b397](https://github.com/noir-lang/noir/commit/9f0b3971ee41e78241cbea4e3f81bac4edd5897d)) +* Ignore compression of blocks after msg.len in sha256_var ([#6206](https://github.com/noir-lang/noir/issues/6206)) ([76eec71](https://github.com/noir-lang/noir/commit/76eec710ff73e5e45fdddcd41ae2cd74e879cfa5)) +* Infer globals to be u32 when used in a type ([#6083](https://github.com/noir-lang/noir/issues/6083)) ([78262c9](https://github.com/noir-lang/noir/commit/78262c96d5b116c77e50653f9059da60824db812)) +* Initialise databus using return values ([#6074](https://github.com/noir-lang/noir/issues/6074)) ([e17dfa5](https://github.com/noir-lang/noir/commit/e17dfa55719f0cfb1080dd25eeda7b70ed44b60d)) +* Let LSP suggest fields and methods in LValue chains ([#6051](https://github.com/noir-lang/noir/issues/6051)) ([5bf6567](https://github.com/noir-lang/noir/commit/5bf6567320629835ef6fa7765ca87e9b38ae4c9a)) +* Let token pretty printer handle `+=` and similar token sequences ([#6135](https://github.com/noir-lang/noir/issues/6135)) ([684b6cc](https://github.com/noir-lang/noir/commit/684b6cc7deb3ed7ecbb2cea4663e8e9a3ae075f0)) +* **mem2reg:** Remove possibility of underflow ([#6107](https://github.com/noir-lang/noir/issues/6107)) ([aea5cc7](https://github.com/noir-lang/noir/commit/aea5cc789ccf4a4d16b1d238d99474f37920b37e)) +* Parse a statement as an expression ([#6040](https://github.com/noir-lang/noir/issues/6040)) ([ab203e4](https://github.com/noir-lang/noir/commit/ab203e4ee902b9137519f9a4261ec368d22f0a25)) +* Pass radix directly to the blackbox ([#6164](https://github.com/noir-lang/noir/issues/6164)) ([82b89c4](https://github.com/noir-lang/noir/commit/82b89c421da80b719922416d574c1bbaa73d55b4)) +* Preserve generic kind on trait methods ([#6099](https://github.com/noir-lang/noir/issues/6099)) ([1df102a](https://github.com/noir-lang/noir/commit/1df102a1ee0eb39dcbada50e10b226c7f7be0f26)) +* Prevent check_can_mutate crashing on undefined variable ([#6044](https://github.com/noir-lang/noir/issues/6044)) ([b3accfc](https://github.com/noir-lang/noir/commit/b3accfc99249ccd198051ecb98cf7962af64a629)) +* Revert mistaken stack size change ([#6212](https://github.com/noir-lang/noir/issues/6212)) ([a37117a](https://github.com/noir-lang/noir/commit/a37117aca3340447d807c1cf3ca79ba573ceaf8b)) +* **ssa:** Check if result of array set is used in value of another array set ([#6197](https://github.com/noir-lang/noir/issues/6197)) ([594ec91](https://github.com/noir-lang/noir/commit/594ec91de55c4cf191d7cdc94a00bb16711cd430)) +* **ssa:** RC correctness issue ([#6134](https://github.com/noir-lang/noir/issues/6134)) ([5b1c896](https://github.com/noir-lang/noir/commit/5b1c896c605ed1047fc17a437e0b58792a778e2d)) +* Type variables by default should have Any kind ([#6203](https://github.com/noir-lang/noir/issues/6203)) ([268f2a0](https://github.com/noir-lang/noir/commit/268f2a0240c507646c65c932748d1bdf062d00b1)) +* Unify macro result type with actual type ([#6086](https://github.com/noir-lang/noir/issues/6086)) ([af52873](https://github.com/noir-lang/noir/commit/af52873dbec9ab980d17d9ba4336181c006a9a53)) +* Update databus in flattening ([#6063](https://github.com/noir-lang/noir/issues/6063)) ([e993da1](https://github.com/noir-lang/noir/commit/e993da1b01aa98deed2af7b5cba2da216fb036a0)) + + +### Miscellaneous Chores + +* Removing implicit numeric generics ([#5837](https://github.com/noir-lang/noir/issues/5837)) ([eda9043](https://github.com/noir-lang/noir/commit/eda904328b269b5926f8a82ab82e52a485903bbe)) + ## [0.34.0](https://github.com/noir-lang/noir/compare/v0.33.0...v0.34.0) (2024-09-13) diff --git a/CRITICAL_NOIR_LIBRARIES b/CRITICAL_NOIR_LIBRARIES new file mode 100644 index 00000000000..c753b76a4fc --- /dev/null +++ b/CRITICAL_NOIR_LIBRARIES @@ -0,0 +1,13 @@ +https://github.com/noir-lang/ec +https://github.com/noir-lang/eddsa +https://github.com/noir-lang/mimc +https://github.com/noir-lang/schnorr +https://github.com/noir-lang/noir_sort +https://github.com/noir-lang/noir-edwards +https://github.com/noir-lang/noir-bignum +https://github.com/noir-lang/noir_bigcurve +https://github.com/noir-lang/noir_base64 +https://github.com/noir-lang/noir_string_search +https://github.com/noir-lang/sparse_array +https://github.com/noir-lang/noir_rsa +https://github.com/noir-lang/noir_json_parser diff --git a/Cargo.lock b/Cargo.lock index cdc1d75a421..4907de7ae62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "acir" -version = "0.50.0" +version = "1.0.0-beta.0" dependencies = [ "acir_field", "base64 0.21.7", @@ -13,7 +13,7 @@ dependencies = [ "criterion", "flate2", "fxhash", - "pprof 0.13.0", + "pprof", "serde", "serde-big-array", "serde-generate", @@ -26,7 +26,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.50.0" +version = "1.0.0-beta.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -40,7 +40,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.50.0" +version = "1.0.0-beta.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -48,6 +48,7 @@ dependencies = [ "ark-bn254", "bn254_blackbox_solver", "brillig_vm", + "fxhash", "indexmap 1.9.3", "num-bigint", "proptest", @@ -59,7 +60,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.50.0" +version = "1.0.0-beta.0" dependencies = [ "acir", "blake2", @@ -71,7 +72,6 @@ dependencies = [ "p256", "proptest", "sha2", - "sha3", "thiserror", ] @@ -90,14 +90,14 @@ dependencies = [ "proptest", "rand 0.8.5", "thiserror", - "toml 0.7.6", + "toml 0.7.8", "tracing-appender", "tracing-subscriber", ] [[package]] name = "acvm_js" -version = "0.50.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -118,9 +118,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -132,15 +132,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "ahash" -version = "0.7.8" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom 0.2.15", - "once_cell", - "version_check", -] +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" @@ -157,13 +152,22 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e0966165eaf052580bd70eb1b32cb3d6245774c0104d1b2793e9650bf83b52a" +dependencies = [ + "equator", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -187,57 +191,58 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "ark-bls12-381" @@ -370,26 +375,27 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "assert_cmd" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" +checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" dependencies = [ "anstyle", - "bstr 1.6.0", + "bstr", "doc-comment", - "predicates 3.0.3", + "libc", + "predicates 3.1.2", "predicates-core", "predicates-tree", "wait-timeout", @@ -397,14 +403,14 @@ dependencies = [ [[package]] name = "assert_fs" -version = "1.0.13" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f070617a68e5c2ed5d06ee8dd620ee18fb72b99f6c094bed34cf8ab07c875b48" +checksum = "7efdb1fdb47602827a342857666feb372712cbc64b414172bd6b167a02927674" dependencies = [ "anstyle", "doc-comment", "globwalk", - "predicates 3.0.3", + "predicates 3.1.2", "predicates-core", "predicates-tree", "tempfile", @@ -416,7 +422,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138985dd8aefbefeaa66b01b7f5b2b6b4c333fcef1cc5f32c63a2aabe37d6de3" dependencies = [ - "futures 0.3.30", + "futures 0.3.31", "lsp-types 0.94.1", "pin-project-lite", "rustix", @@ -432,21 +438,21 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -469,6 +475,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.6.0" @@ -507,9 +519,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitmaps" @@ -554,9 +566,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" dependencies = [ "arrayref", "arrayvec", @@ -589,7 +601,7 @@ dependencies = [ [[package]] name = "bn254_blackbox_solver" -version = "0.50.0" +version = "1.0.0-beta.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -602,12 +614,12 @@ dependencies = [ "lazy_static", "noir_grumpkin", "num-bigint", - "pprof 0.12.1", + "pprof", ] [[package]] name = "brillig" -version = "0.50.0" +version = "1.0.0-beta.0" dependencies = [ "acir_field", "serde", @@ -615,7 +627,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.50.0" +version = "1.0.0-beta.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -626,31 +638,20 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata 0.1.10", -] - -[[package]] -name = "bstr" -version = "1.6.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", - "regex-automata 0.3.9", + "regex-automata 0.4.8", "serde", ] [[package]] name = "build-data" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac83c47416b2db78a5a8a45d7d229a730b62806fa41ac6b4dbde6d016798776" +checksum = "aed3884e2cab7c973c8fd2d150314b6a932df7fdc830edcaf1e8e7c4ae9db3c0" dependencies = [ "chrono", "safe-lock", @@ -659,48 +660,42 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "bytecount" -version = "0.6.3" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.13.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "camino" -version = "1.1.6" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.3" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -727,11 +722,11 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.83" +version = "1.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" dependencies = [ - "libc", + "shlex", ] [[package]] @@ -761,19 +756,11 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "chumsky" -version = "0.8.0" -source = "git+https://github.com/jfecher/chumsky?rev=ad9d312#ad9d312d9ffbc66c14514fa2b5752f4127b44f1e" -dependencies = [ - "hashbrown 0.11.2", -] - [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -782,15 +769,15 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", @@ -798,9 +785,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.11" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -816,9 +803,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.11" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -826,23 +813,32 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_complete" +version = "4.5.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11611dca53440593f38e6b25ec629de50b14cdfa63adc0fb856115a2c6d97595" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clipboard-win" @@ -873,7 +869,7 @@ checksum = "fc4159b76af02757139baf42c0c971c6dc155330999fbfd8eddb29b97fb2db68" dependencies = [ "codespan-reporting", "lsp-types 0.88.0", - "url 2.5.0", + "url 2.5.4", ] [[package]] @@ -889,9 +885,9 @@ dependencies = [ [[package]] name = "color-eyre" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" dependencies = [ "backtrace", "color-spantrace", @@ -904,9 +900,9 @@ dependencies = [ [[package]] name = "color-spantrace" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" dependencies = [ "once_cell", "owo-colors", @@ -916,9 +912,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "comma" @@ -950,30 +946,30 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.4" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const-str" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aca749d3d3f5b87a0d6100509879f9cf486ab510803a4a4e1001da1ff61c2bd6" +checksum = "3618cccc083bb987a415d85c02ca6c9994ea5b44731ec28b9ecf09658655fba9" [[package]] name = "const_format" -version = "0.2.31" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.31" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" dependencies = [ "proc-macro2", "quote", @@ -982,9 +978,9 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "convert_case" @@ -1003,33 +999,33 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpp_demangle" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee34052ee3d93d6d8f3e6f81d85c47921f6653a19a7b70e939e3e602d893a674" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if 1.0.0", ] @@ -1072,43 +1068,43 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.9" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c3242926edf34aec4ac3a77108ad4854bffaa2e4ddc1824124ce59231302d5" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if 1.0.0", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if 1.0.0", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if 1.0.0", "crossbeam-utils", - "memoffset 0.9.1", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" @@ -1134,9 +1130,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.2.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" dependencies = [ "csv-core", "itoa", @@ -1146,9 +1142,9 @@ dependencies = [ [[package]] name = "csv-core" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" dependencies = [ "memchr", ] @@ -1166,9 +1162,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.3" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -1176,40 +1172,41 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "dashmap" -version = "5.5.3" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if 1.0.0", + "crossbeam-utils", "hashbrown 0.14.5", "lock_api", "once_cell", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.10", ] [[package]] @@ -1233,10 +1230,11 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.7" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ + "powerfmt", "serde", ] @@ -1253,15 +1251,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.87", ] [[package]] @@ -1322,6 +1320,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -1357,9 +1366,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -1399,15 +1408,45 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", +] + [[package]] name = "env_logger" -version = "0.10.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ + "env_filter", "log", ] +[[package]] +name = "equator" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c35da53b5a021d2484a7cc49b2ac7f2d840f8236a286f84202369bd338d761ea" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf679796c0322556351f287a51b49e48f7c4986e727b5dd78c972d30e2e16cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1436,9 +1475,9 @@ dependencies = [ [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -1446,9 +1485,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fd-lock" @@ -1494,23 +1533,33 @@ dependencies = [ [[package]] name = "file-id" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6584280525fb2059cba3db2c04abf947a1a29a45ddae89f3870f8281704fafc9" +checksum = "6bc904b9bbefcadbd8e3a9fb0d464a9b979de6324c03b3c663e8994f46a5be36" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "file-lock" +version = "2.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "040b48f80a749da50292d0f47a1e2d5bf1d772f52836c07f64bfccc62ba6e664" +dependencies = [ + "cc", + "libc", ] [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.3.5", - "windows-sys 0.48.0", + "libredox 0.1.3", + "windows-sys 0.59.0", ] [[package]] @@ -1533,12 +1582,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1552,7 +1601,7 @@ dependencies = [ [[package]] name = "fm" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "codespan-reporting", "iter-extended", @@ -1597,9 +1646,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1612,9 +1661,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1622,15 +1671,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1640,38 +1689,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures 0.1.31", "futures-channel", @@ -1731,9 +1780,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -1743,24 +1792,24 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.11" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", - "bstr 1.6.0", - "fnv", + "bstr", "log", - "regex", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] name = "globwalk" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "ignore", "walkdir", ] @@ -1803,9 +1852,13 @@ dependencies = [ [[package]] name = "half" -version = "1.8.2" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if 1.0.0", + "crunchy", +] [[package]] name = "halo2" @@ -1830,15 +1883,6 @@ dependencies = [ "rayon", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.8", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -1851,7 +1895,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.11", + "ahash", ] [[package]] @@ -1860,6 +1904,12 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" + [[package]] name = "heck" version = "0.3.3" @@ -1875,11 +1925,23 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "hex" @@ -1898,9 +1960,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1909,9 +1971,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -1920,21 +1982,21 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -1961,9 +2023,9 @@ checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678" [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1982,6 +2044,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2001,27 +2181,37 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] name = "ignore" -version = "0.4.20" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" dependencies = [ + "crossbeam-deque", "globset", - "lazy_static", "log", "memchr", - "regex", + "regex-automata 0.4.8", "same-file", - "thread_local", "walkdir", "winapi-util", ] @@ -2084,28 +2274,28 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.1", "serde", ] [[package]] name = "inferno" -version = "0.11.19" +version = "0.11.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" +checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" dependencies = [ - "ahash 0.8.11", + "ahash", "clap", "crossbeam-channel", "crossbeam-utils", "dashmap", "env_logger", - "indexmap 2.2.6", + "indexmap 2.6.0", "is-terminal", "itoa", "log", @@ -2138,27 +2328,33 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi", - "rustix", - "windows-sys 0.48.0", + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.52.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "iter-extended" -version = "0.34.0" +version = "1.0.0-beta.0" [[package]] name = "itertools" @@ -2171,9 +2367,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" @@ -2203,7 +2399,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.30", + "futures 0.3.31", "jsonrpc-core", "jsonrpc-pubsub", "log", @@ -2218,7 +2414,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.30", + "futures 0.3.31", "futures-executor", "futures-util", "log", @@ -2233,7 +2429,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.30", + "futures 0.3.31", "jsonrpc-client-transports", ] @@ -2255,7 +2451,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.30", + "futures 0.3.31", "hyper", "jsonrpc-core", "jsonrpc-server-utils", @@ -2271,7 +2467,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.30", + "futures 0.3.31", "jsonrpc-core", "lazy_static", "log", @@ -2287,7 +2483,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes", - "futures 0.3.30", + "futures 0.3.31", "globset", "jsonrpc-core", "lazy_static", @@ -2326,9 +2522,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -2355,9 +2551,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ "spin", ] @@ -2370,15 +2566,15 @@ checksum = "82903360c009b816f5ab72a9b68158c27c301ee2c3f20655b55c5e589e7d3bb7" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libm" -version = "0.2.7" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -2386,22 +2582,51 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", "redox_syscall 0.4.1", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall 0.5.7", +] + +[[package]] +name = "light-poseidon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c9a85a9752c549ceb7578064b4ed891179d20acd85f27318573b64d2d7ee7ee" +dependencies = [ + "ark-bn254", + "ark-ff", + "num-bigint", + "thiserror", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -2409,9 +2634,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "louds-rs" @@ -2432,7 +2657,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "url 2.5.0", + "url 2.5.4", ] [[package]] @@ -2445,7 +2670,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "url 2.5.0", + "url 2.5.4", ] [[package]] @@ -2465,15 +2690,15 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" -version = "0.5.10" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] @@ -2487,15 +2712,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "memuse" version = "0.2.1" @@ -2511,11 +2727,20 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "minreq" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3371dfc7b772c540da1380123674a8e20583aca99907087d990ca58cf44203" +checksum = "763d142cdff44aaadd9268bebddb156ef6c65a0e13486bb81673cf2d8739f9b0" dependencies = [ "log", "serde", @@ -2534,9 +2759,21 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + [[package]] name = "nargo" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "fm", @@ -2556,16 +2793,17 @@ dependencies = [ "rand 0.8.5", "rayon", "serde", - "tempfile", "thiserror", "tracing", + "walkdir", ] [[package]] name = "nargo_cli" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", + "ark-bn254", "assert_cmd", "assert_fs", "async-lsp", @@ -2573,14 +2811,19 @@ dependencies = [ "build-data", "clap", "clap-markdown", + "clap_complete", "color-eyre", "const_format", "criterion", "dap", "dirs", + "file-lock", "fm", + "fxhash", "iai", "iter-extended", + "lazy_static", + "light-poseidon", "nargo", "nargo_fmt", "nargo_toml", @@ -2594,21 +2837,25 @@ dependencies = [ "notify", "notify-debouncer-full", "paste", - "pprof 0.13.0", + "pprof", "predicates 2.1.5", "prettytable-rs", + "proptest", "rayon", "serde", "serde_json", + "sha2", + "sha3", "similar-asserts", "tempfile", "termcolor", "termion", "test-binary", + "test-case", "thiserror", "tokio", - "tokio-util 0.7.10", - "toml 0.7.6", + "tokio-util 0.7.12", + "toml 0.7.8", "tower", "tracing-appender", "tracing-subscriber", @@ -2616,19 +2863,18 @@ dependencies = [ [[package]] name = "nargo_fmt" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ - "bytecount", "noirc_frontend", "serde", "similar-asserts", "thiserror", - "toml 0.7.6", + "toml 0.7.8", ] [[package]] name = "nargo_toml" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "dirs", "fm", @@ -2637,9 +2883,11 @@ dependencies = [ "noirc_frontend", "semver", "serde", + "tempfile", + "test-case", "thiserror", - "toml 0.7.6", - "url 2.5.0", + "toml 0.7.8", + "url 2.5.4", ] [[package]] @@ -2672,7 +2920,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "libc", - "memoffset 0.6.5", + "memoffset", ] [[package]] @@ -2685,7 +2933,7 @@ dependencies = [ "bitflags 1.3.2", "cfg-if 1.0.0", "libc", - "memoffset 0.6.5", + "memoffset", "pin-utils", ] @@ -2702,7 +2950,7 @@ dependencies = [ [[package]] name = "noir_debugger" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "assert_cmd", @@ -2726,7 +2974,7 @@ dependencies = [ [[package]] name = "noir_fuzzer" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "noirc_abi", @@ -2749,11 +2997,10 @@ dependencies = [ [[package]] name = "noir_lsp" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "async-lsp", - "chumsky", "codespan-lsp", "convert_case 0.6.0", "fm", @@ -2762,14 +3009,12 @@ dependencies = [ "nargo", "nargo_fmt", "nargo_toml", - "noirc_artifacts", "noirc_driver", "noirc_errors", "noirc_frontend", "rayon", "serde", "serde_json", - "serde_with", "strum", "thiserror", "tokio", @@ -2779,19 +3024,23 @@ dependencies = [ [[package]] name = "noir_profiler" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acir", + "bn254_blackbox_solver", "clap", "color-eyre", "const_format", "fm", + "fxhash", "im", "inferno", + "nargo", "noirc_abi", "noirc_artifacts", "noirc_driver", "noirc_errors", + "noirc_evaluator", "serde", "serde_json", "tempfile", @@ -2801,7 +3050,7 @@ dependencies = [ [[package]] name = "noir_wasm" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "build-data", @@ -2825,7 +3074,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "iter-extended", @@ -2833,18 +3082,18 @@ dependencies = [ "num-bigint", "num-traits", "proptest", - "proptest-derive", + "proptest-derive 0.4.0", "serde", "serde_json", "strum", "strum_macros", "thiserror", - "toml 0.7.6", + "toml 0.7.8", ] [[package]] name = "noirc_abi_wasm" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "build-data", @@ -2861,11 +3110,11 @@ dependencies = [ [[package]] name = "noirc_arena" -version = "0.34.0" +version = "1.0.0-beta.0" [[package]] name = "noirc_artifacts" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "codespan-reporting", @@ -2880,7 +3129,7 @@ dependencies = [ [[package]] name = "noirc_driver" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "build-data", @@ -2899,11 +3148,10 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "base64 0.21.7", - "chumsky", "codespan", "codespan-reporting", "flate2", @@ -2917,7 +3165,7 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -2929,24 +3177,27 @@ dependencies = [ "noirc_errors", "noirc_frontend", "num-bigint", + "num-traits", "proptest", "rayon", "serde", "serde_json", "serde_with", + "similar-asserts", + "test-case", "thiserror", "tracing", + "tracing-test", ] [[package]] name = "noirc_frontend" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "base64 0.21.7", "bn254_blackbox_solver", "cfg-if 1.0.0", - "chumsky", "fm", "im", "iter-extended", @@ -2956,8 +3207,9 @@ dependencies = [ "num-bigint", "num-traits", "petgraph", + "proptest", + "proptest-derive 0.5.0", "rangemap", - "regex", "rustc-hash", "serde", "serde_json", @@ -2971,12 +3223,11 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "0.34.0" +version = "1.0.0-beta.0" dependencies = [ "acvm", "iter-extended", "jsonrpc", - "regex", "serde", "serde_json", "thiserror", @@ -2994,7 +3245,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "crossbeam-channel", "filetime", "fsevent-sys", @@ -3002,22 +3253,22 @@ dependencies = [ "kqueue", "libc", "log", - "mio", + "mio 0.8.11", "walkdir", "windows-sys 0.48.0", ] [[package]] name = "notify-debouncer-full" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f5dab59c348b9b50cf7f261960a20e389feb2713636399cd9082cd4b536154" +checksum = "fb7fd166739789c9ff169e654dc1501373db9d80a4c3f972817c8a4d7cf8f34e" dependencies = [ "crossbeam-channel", "file-id", "log", "notify", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "walkdir", ] @@ -3033,15 +3284,20 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-format" version = "0.4.4" @@ -3054,19 +3310,18 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -3078,7 +3333,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -3090,24 +3345,24 @@ checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" [[package]] name = "object" -version = "0.31.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "overload" @@ -3154,12 +3409,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.10", ] [[package]] @@ -3178,15 +3433,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.5.7", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -3221,9 +3476,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "percent-encoding" @@ -3239,12 +3494,12 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.2.6", + "indexmap 2.6.0", ] [[package]] @@ -3293,9 +3548,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -3315,15 +3570,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "num-traits", "plotters-backend", @@ -3334,47 +3589,32 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] [[package]] -name = "pprof" -version = "0.12.1" +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978385d59daf9269189d052ca8a84c1acfd0715c0599a5d5188d4acc078ca46a" -dependencies = [ - "backtrace", - "cfg-if 1.0.0", - "criterion", - "findshlibs", - "inferno", - "libc", - "log", - "nix 0.26.4", - "once_cell", - "parking_lot 0.12.1", - "smallvec", - "symbolic-demangle", - "tempfile", - "thiserror", -] +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "pprof" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5c97c51bd34c7e742402e216abdeb44d415fbe6ae41d56b114723e953711cb" +checksum = "ebbe2f8898beba44815fdc9e5a4ae9c929e21c5dc29b0c774a15555f7f58d6d0" dependencies = [ + "aligned-vec", "backtrace", "cfg-if 1.0.0", "criterion", @@ -3384,7 +3624,7 @@ dependencies = [ "log", "nix 0.26.4", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "smallvec", "symbolic-demangle", "tempfile", @@ -3393,9 +3633,12 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "predicates" @@ -3413,27 +3656,26 @@ dependencies = [ [[package]] name = "predicates" -version = "3.0.3" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" dependencies = [ "anstyle", "difflib", - "itertools", "predicates-core", ] [[package]] name = "predicates-core" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" [[package]] name = "predicates-tree" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" dependencies = [ "predicates-core", "termtree", @@ -3470,28 +3712,28 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.5.0", + "bitflags 2.6.0", "lazy_static", "num-traits", "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", "rusty-fork", "tempfile", "unarray", @@ -3508,6 +3750,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "proptest-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -3525,9 +3778,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -3639,9 +3892,9 @@ dependencies = [ [[package]] name = "rangemap" -version = "1.4.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "977b1e897f9d764566891689e642653e5ed90c6895106acd005eb4c1d0203991" +checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684" [[package]] name = "rayon" @@ -3674,20 +3927,20 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] @@ -3698,25 +3951,25 @@ checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb" [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.15", - "redox_syscall 0.2.16", + "libredox 0.1.3", "thiserror", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.2", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -3730,19 +3983,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" - -[[package]] -name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", ] [[package]] @@ -3753,9 +4000,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rexpect" @@ -3783,9 +4030,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.36" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] @@ -3810,7 +4057,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.64", + "syn 2.0.87", "walkdir", ] @@ -3826,9 +4073,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -3838,20 +4085,20 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -3860,9 +4107,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "rusty-fork" @@ -3912,23 +4159,23 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safe-lock" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "077d73db7973cccf63eb4aff1e5a34dc2459baa867512088269ea5f2f4253c90" +checksum = "f29841ed0a577196bca5b753cd4e4022fa50b718e56fc0d35919ed32e20ec65c" [[package]] name = "safe-proc-macro2" -version = "1.0.36" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "814c536dcd27acf03296c618dab7ad62d28e70abd7ba41d3f34a2ce707a2c666" +checksum = "7fd85be67db87168aa3c13fd0da99f48f2ab005dccad5af5626138dc1df20eb6" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -3942,18 +4189,18 @@ dependencies = [ [[package]] name = "safe-regex" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15289bf322e0673d52756a18194167f2378ec1a15fe884af6e2d2cb934822b0" +checksum = "e6ab4bc484ef480a9ce79b381efd7b6767700f514d47bc599036e9d6f7f3c49d" dependencies = [ "safe-regex-macro", ] [[package]] name = "safe-regex-compiler" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba76fae590a2aa665279deb1f57b5098cbace01a0c5e60e262fcf55f7c51542" +checksum = "6d71f8c78bffb07962595e1bfa5ed11d24dd855eedc50b6a735f5ef648ce621b" dependencies = [ "safe-proc-macro2", "safe-quote", @@ -3961,9 +4208,9 @@ dependencies = [ [[package]] name = "safe-regex-macro" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c2e96b5c03f158d1b16ba79af515137795f4ad4e8de3f790518aae91f1d127" +checksum = "0909ab4b77511df24201cd66541d6a028887c77ecc065f277c68a12a663274ef" dependencies = [ "safe-proc-macro2", "safe-regex-compiler", @@ -4006,18 +4253,18 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.209" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] @@ -4058,58 +4305,60 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_repr" -version = "0.1.14" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] [[package]] name = "serde_with" -version = "3.2.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1402f54f9a3b9e2efe71c1cea24e648acce55887983553eeb858cf3115acfd49" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.6", + "indexmap 2.6.0", "serde", + "serde_derive", "serde_json", "serde_with_macros", "time", @@ -4117,21 +4366,21 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.2.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9197f1ad0e3c173a0222d3c4404fb04c3afe87e962bcb327af73e8301fa203c7" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -4150,9 +4399,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -4163,6 +4412,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signature" version = "1.6.4" @@ -4175,19 +4430,19 @@ dependencies = [ [[package]] name = "similar" -version = "2.3.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" dependencies = [ - "bstr 0.2.17", + "bstr", "unicode-segmentation", ] [[package]] name = "similar-asserts" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e041bb827d1bfca18f213411d51b665309f1afb37a04a5d1464530e13779fc0f" +checksum = "cfe85670573cd6f0fa97940f26e7e6601213c3b0555246c24234131f88c5709e" dependencies = [ "console", "similar", @@ -4211,9 +4466,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] @@ -4250,19 +4505,19 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "spin" -version = "0.5.2" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" @@ -4300,9 +4555,9 @@ checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -4325,15 +4580,15 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symbolic-common" -version = "12.3.0" +version = "12.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167a4ffd7c35c143fd1030aa3c2caf76ba42220bd5a6b5f4781896434723b8c3" +checksum = "3d4d73159efebfb389d819fd479afb2dbd57dcb3e3f4b7fcfa0e675f5a46c1cb" dependencies = [ "debugid", "memmap2", @@ -4343,9 +4598,9 @@ dependencies = [ [[package]] name = "symbolic-demangle" -version = "12.3.0" +version = "12.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e378c50e80686c1c5c205674e1f86a2858bec3d2a7dfdd690331a8a19330f293" +checksum = "a767859f6549c665011970874c3f541838b4835d5aaaa493d3ee383918be9f10" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -4365,15 +4620,26 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.64" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "tap" version = "1.0.1" @@ -4382,15 +4648,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if 1.0.0", "fastrand", - "redox_syscall 0.3.5", + "once_cell", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -4406,9 +4672,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -4420,7 +4686,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "417813675a504dfbbf21bfde32c03e5bf9f2413999962b479023c02848c1c7a5" dependencies = [ "libc", - "libredox", + "libredox 0.0.2", "numtoa", "redox_termios", ] @@ -4444,6 +4710,39 @@ dependencies = [ "thiserror", ] +[[package]] +name = "test-case" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8" +dependencies = [ + "test-case-macros", +] + +[[package]] +name = "test-case-core" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f" +dependencies = [ + "cfg-if 1.0.0", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "test-case-macros" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "test-case-core", +] + [[package]] name = "textwrap" version = "0.13.4" @@ -4467,29 +4766,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if 1.0.0", "once_cell", @@ -4497,12 +4796,14 @@ dependencies = [ [[package]] name = "time" -version = "0.3.25" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", + "powerfmt", "serde", "time-core", "time-macros", @@ -4510,19 +4811,30 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.11" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -4535,9 +4847,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -4550,37 +4862,36 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.1" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", + "mio 1.0.2", "pin-project-lite", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -4603,9 +4914,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -4626,9 +4937,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", @@ -4638,20 +4949,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -4671,15 +4982,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -4713,7 +5024,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] @@ -4765,6 +5076,27 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "tracing-test" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "557b891436fe0d5e0e363427fc7f217abf9ccd510d5136549847bdcbcd011d68" +dependencies = [ + "tracing-core", + "tracing-subscriber", + "tracing-test-macro", +] + +[[package]] +name = "tracing-test-macro" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" +dependencies = [ + "quote", + "syn 2.0.87", +] + [[package]] name = "tracing-web" version = "0.1.3" @@ -4789,15 +5121,15 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unarray" @@ -4807,24 +5139,21 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-linebreak" @@ -4834,30 +5163,30 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "url" @@ -4872,27 +5201,39 @@ dependencies = [ [[package]] name = "url" -version = "2.5.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.3", "percent-encoding 2.3.1", "serde", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.4.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" [[package]] name = "valuable" @@ -4902,9 +5243,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wait-timeout" @@ -4917,12 +5258,12 @@ dependencies = [ [[package]] name = "waitpid-any" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54f8c3c56044fc359f905b72879576a15d49c46d085ed6266a98826716f14033" +checksum = "0189157c93c54d86e5c61ddf0c1223baa25e5bfb2f6f9983c678985b028d7c12" dependencies = [ "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4979,7 +5320,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -5013,7 +5354,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5076,11 +5417,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -5091,11 +5432,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.50.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af6041b3f84485c21b57acdc0fee4f4f0c93f426053dc05fa5d6fc262537bbff" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -5116,6 +5457,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -5239,13 +5589,25 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.5.0" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -5255,31 +5617,77 @@ dependencies = [ "tap", ] +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", +] + [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", + "synstructure", ] [[package]] name = "zeroize" -version = "1.6.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -5292,7 +5700,29 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a6cfa7de07f..0acee2a040b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ resolver = "2" [workspace.package] # x-release-please-start-version -version = "0.34.0" +version = "1.0.0-beta.0" # x-release-please-end authors = ["The Noir Team "] edition = "2021" @@ -57,13 +57,13 @@ unused_qualifications = "warn" [workspace.dependencies] # ACVM workspace dependencies -acir_field = { version = "0.50.0", path = "acvm-repo/acir_field", default-features = false } -acir = { version = "0.50.0", path = "acvm-repo/acir", default-features = false } -acvm = { version = "0.50.0", path = "acvm-repo/acvm" } -brillig = { version = "0.50.0", path = "acvm-repo/brillig", default-features = false } -brillig_vm = { version = "0.50.0", path = "acvm-repo/brillig_vm", default-features = false } -acvm_blackbox_solver = { version = "0.50.0", path = "acvm-repo/blackbox_solver", default-features = false } -bn254_blackbox_solver = { version = "0.50.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false } +acir_field = { version = "1.0.0-beta.0", path = "acvm-repo/acir_field", default-features = false } +acir = { version = "1.0.0-beta.0", path = "acvm-repo/acir", default-features = false } +acvm = { version = "1.0.0-beta.0", path = "acvm-repo/acvm" } +brillig = { version = "1.0.0-beta.0", path = "acvm-repo/brillig", default-features = false } +brillig_vm = { version = "1.0.0-beta.0", path = "acvm-repo/brillig_vm", default-features = false } +acvm_blackbox_solver = { version = "1.0.0-beta.0", path = "acvm-repo/blackbox_solver", default-features = false } +bn254_blackbox_solver = { version = "1.0.0-beta.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false } # Noir compiler workspace dependencies fm = { path = "compiler/fm" } @@ -87,8 +87,12 @@ bb_abstraction_leaks = { path = "tooling/bb_abstraction_leaks" } acvm_cli = { path = "tooling/acvm_cli" } # Arkworks -ark-bn254 = { version = "^0.4.0", default-features = false, features = ["curve"] } -ark-bls12-381 = { version = "^0.4.0", default-features = false, features = ["curve"] } +ark-bn254 = { version = "^0.4.0", default-features = false, features = [ + "curve", +] } +ark-bls12-381 = { version = "^0.4.0", default-features = false, features = [ + "curve", +] } grumpkin = { version = "0.1.0", package = "noir_grumpkin", features = ["std"] } ark-ec = { version = "^0.4.0", default-features = false } ark-ff = { version = "^0.4.0", default-features = false } @@ -117,16 +121,12 @@ clap = { version = "4.3.19", features = ["derive", "env"] } codespan = { version = "0.11.1", features = ["serialization"] } codespan-lsp = "0.11.1" codespan-reporting = "0.11.1" -chumsky = { git = "https://github.com/jfecher/chumsky", rev = "ad9d312", default-features = false, features = [ - "ahash", - "std", -] } # Benchmarking criterion = "0.5.0" # Note that using the "frame-pointer" feature breaks framegraphs on linux # https://github.com/tikv/pprof-rs/pull/172 -pprof = { version = "0.13", features = ["flamegraph", "criterion"] } +pprof = { version = "0.14", features = ["flamegraph", "criterion"] } cfg-if = "1.0.0" dirs = "4" @@ -135,17 +135,19 @@ serde_json = "1.0" smol_str = { version = "0.1.17", features = ["serde"] } thiserror = "1.0.21" toml = "0.7.2" -url = "2.2.0" +url = "2.5.4" base64 = "0.21.2" fxhash = "0.2.1" build-data = "0.1.3" bincode = "1.3.3" hex = "0.4.2" const_format = "0.2.30" +lazy_static = "1.4" num-bigint = "0.4" num-traits = "0.2" similar-asserts = "1.5.0" tempfile = "3.6.0" +test-case = "3.3.1" jsonrpc = { version = "0.16.0", features = ["minreq_http"] } flate2 = "1.0.24" color-eyre = "0.6.2" @@ -153,6 +155,10 @@ rand = "0.8.5" proptest = "1.2.0" proptest-derive = "0.4.0" rayon = "1.8.0" +sha2 = { version = "0.10.6", features = ["compress"] } +sha3 = "0.10.6" +strum = "0.24" +strum_macros = "0.24" im = { version = "15.1", features = ["serde"] } tracing = "0.1.40" diff --git a/README.md b/README.md index eea2280c50c..7f5cd5ce522 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Noir is free and open source. It is distributed under a dual license. (MIT/APACH Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this repository by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. [Noir]: https://www.noir-lang.org/ -[Getting Started]: https://noir-lang.org/docs/getting_started/installation/ +[Getting Started]: https://noir-lang.org/docs/getting_started/quick_start/ [Forum]: https://forum.aztec.network/c/noir [Discord]: https://discord.gg/JtqzkdeQ6G [Documentation]: https://noir-lang.org/docs diff --git a/acvm-repo/CHANGELOG.md b/acvm-repo/CHANGELOG.md index 8d47e10c45a..70d5840be6a 100644 --- a/acvm-repo/CHANGELOG.md +++ b/acvm-repo/CHANGELOG.md @@ -5,6 +5,575 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.55.0](https://github.com/noir-lang/noir/compare/v0.54.0...v0.55.0) (2024-11-19) + + +### ⚠ BREAKING CHANGES + +* Remove `recursive` from ACIR format; add them to API and CLI (https://github.com/AztecProtocol/aztec-packages/pull/9479) +* **avm/brillig:** revert/rethrow oracle (https://github.com/AztecProtocol/aztec-packages/pull/9408) +* use Brillig opcode when possible for less-than operations on fields (https://github.com/AztecProtocol/aztec-packages/pull/9416) +* remove noir_js_backend_barretenberg (https://github.com/AztecProtocol/aztec-packages/pull/9338) +* replace usage of vector in keccakf1600 input with array (https://github.com/AztecProtocol/aztec-packages/pull/9350) +* **profiler:** New flamegraph command that profiles the opcodes executed ([#6327](https://github.com/noir-lang/noir/issues/6327)) +* remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) +* remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) +* remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) +* **avm:** remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) +* remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) +* add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) +* **avm:** variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) +* **avm/brillig:** take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) + +### Features + +* (bb) 128-bit challenges (https://github.com/AztecProtocol/aztec-packages/pull/8406) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Add assertions for ACVM `FunctionInput` `bit_size` ([#5864](https://github.com/noir-lang/noir/issues/5864)) ([8712f4c](https://github.com/noir-lang/noir/commit/8712f4c20d23f3809bcfb03f2e3ba0e5ace20a1d)) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Add recursive aggregation object to proving/verification keys (https://github.com/AztecProtocol/aztec-packages/pull/6770) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Add reusable procedures to brillig generation (https://github.com/AztecProtocol/aztec-packages/pull/7981) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Added indirect const instruction (https://github.com/AztecProtocol/aztec-packages/pull/8065) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Adding aggregation to honk and rollup (https://github.com/AztecProtocol/aztec-packages/pull/7466) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Automate verify_honk_proof input generation (https://github.com/AztecProtocol/aztec-packages/pull/8092) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **avm/brillig:** Revert/rethrow oracle (https://github.com/AztecProtocol/aztec-packages/pull/9408) ([321a493](https://github.com/noir-lang/noir/commit/321a493216e19a2f077007c3447a3030db0df0d0)) +* **avm/brillig:** Take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **avm:** Variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Change the layout of arrays and vectors to be a single pointer (https://github.com/AztecProtocol/aztec-packages/pull/8448) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Encode static error strings in the ABI (https://github.com/AztecProtocol/aztec-packages/pull/9552) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) +* Ensure that generated ACIR is solvable ([#6415](https://github.com/noir-lang/noir/issues/6415)) ([b473d99](https://github.com/noir-lang/noir/commit/b473d99b2b70b595596b8392617256dbaf5d5642)) +* Hook up secondary calldata column in dsl (https://github.com/AztecProtocol/aztec-packages/pull/7759) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Integrate databus in the private kernels (https://github.com/AztecProtocol/aztec-packages/pull/9028) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Make token transfer be recursive (https://github.com/AztecProtocol/aztec-packages/pull/7730) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* New test programs for wasm benchmarking (https://github.com/AztecProtocol/aztec-packages/pull/8389) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Note hashes as points (https://github.com/AztecProtocol/aztec-packages/pull/7618) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize allocating immediate amounts of memory (https://github.com/AztecProtocol/aztec-packages/pull/8579) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Optimize constant array handling in brillig_gen (https://github.com/AztecProtocol/aztec-packages/pull/7661) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize to_radix (https://github.com/AztecProtocol/aztec-packages/pull/8073) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Parallelize DIE pass (https://github.com/AztecProtocol/aztec-packages/pull/9933) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) +* Pass calldata ids to the backend (https://github.com/AztecProtocol/aztec-packages/pull/7875) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Poseidon2 gates for Ultra arithmetisation (https://github.com/AztecProtocol/aztec-packages/pull/7494) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **profiler:** Add support for brillig functions in opcodes-flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7698) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* **profiler:** New flamegraph command that profiles the opcodes executed ([#6327](https://github.com/noir-lang/noir/issues/6327)) ([4d87c9a](https://github.com/noir-lang/noir/commit/4d87c9ac78b48b4bd0ae81316df28aab390d004e)) +* Remove 'single use' intermediate variables ([#6268](https://github.com/noir-lang/noir/issues/6268)) ([ec75e8e](https://github.com/noir-lang/noir/commit/ec75e8ec59e0f2a2169aea67372411ede4074d09)) +* Remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Removing superfluous call to MSM (https://github.com/AztecProtocol/aztec-packages/pull/7708) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Report gates and VKs of private protocol circuits with megahonk (https://github.com/AztecProtocol/aztec-packages/pull/7722) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Simplify constant calls to `poseidon2_permutation`, `schnorr_verify` and `embedded_curve_add` ([#5140](https://github.com/noir-lang/noir/issues/5140)) ([2823ba7](https://github.com/noir-lang/noir/commit/2823ba7242db788ca1d7f6e7a48be2f1de62f278)) +* Simplify constant MSM calls in SSA ([#6547](https://github.com/noir-lang/noir/issues/6547)) ([f291e37](https://github.com/noir-lang/noir/commit/f291e3702589a5cd043acfded5e187f56ec765cc)) +* Small optimization in toradix (https://github.com/AztecProtocol/aztec-packages/pull/8040) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Stop with HeapVector (https://github.com/AztecProtocol/aztec-packages/pull/9810) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7743) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7862) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7945) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7958) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8008) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8093) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8125) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8237) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8423) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8435) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8466) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8482) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8512) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8526) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8934) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9034) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9099) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9275) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9711) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) +* **test:** Fuzz test poseidon2 hash equivalence ([#6265](https://github.com/noir-lang/noir/issues/6265)) ([f61ba03](https://github.com/noir-lang/noir/commit/f61ba037c6726e19be4f894d9447fe396df95417)) +* **test:** Fuzz test stdlib hash functions ([#6233](https://github.com/noir-lang/noir/issues/6233)) ([1a2ca46](https://github.com/noir-lang/noir/commit/1a2ca46af0d1c05813dbe28670a2bc39b79e4c9f)) +* TXE nr deployments, dependency cleanup for CLI (https://github.com/AztecProtocol/aztec-packages/pull/7548) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Unify all acir recursion constraints based on RecursionConstraint and proof_type (https://github.com/AztecProtocol/aztec-packages/pull/7993) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) + + +### Bug Fixes + +* **debugger:** Update the debugger to handle the new Brillig debug metadata format ([#5706](https://github.com/noir-lang/noir/issues/5706)) ([a31f82e](https://github.com/noir-lang/noir/commit/a31f82e598def60d00c65b79b8c5411f8aa832aa)) +* Deflatten databus visibilities (https://github.com/AztecProtocol/aztec-packages/pull/7761) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Discard optimisation that would change execution ordering or that is related to call outputs ([#6461](https://github.com/noir-lang/noir/issues/6461)) ([b8654f7](https://github.com/noir-lang/noir/commit/b8654f700b218cc09c5381af65df11ead9ffcdaf)) +* Display every bit in integer tokens ([#6360](https://github.com/noir-lang/noir/issues/6360)) ([b985fdf](https://github.com/noir-lang/noir/commit/b985fdf6e635570b8db3af83d9ec14e7cd749062)) +* Do not duplicate redundant Brillig debug metadata ([#5696](https://github.com/noir-lang/noir/issues/5696)) ([e4f7dbe](https://github.com/noir-lang/noir/commit/e4f7dbe63b55807b3ff0b4d6f47a8b7f847299fb)) +* Export brillig names in contract functions (https://github.com/AztecProtocol/aztec-packages/pull/8212) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Handle multiple entry points for Brillig call stack resolution after metadata deduplication ([#5788](https://github.com/noir-lang/noir/issues/5788)) ([38fe9dd](https://github.com/noir-lang/noir/commit/38fe9dda111952fdb894df90a319c087382edfc9)) +* Homogeneous input points for EC ADD ([#6241](https://github.com/noir-lang/noir/issues/6241)) ([f6a7306](https://github.com/noir-lang/noir/commit/f6a7306436ea1a37ec7f3b884721b50467e9a063)) +* Reject invalid expression with in CLI parser ([#6287](https://github.com/noir-lang/noir/issues/6287)) ([052aee8](https://github.com/noir-lang/noir/commit/052aee80ff3e1e4fd2ca45310d7bb8b980af126a)) +* Remove need for duplicate attributes on each function (https://github.com/AztecProtocol/aztec-packages/pull/9244) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Restrict keccak256_injective test input to 8 bits ([#5977](https://github.com/noir-lang/noir/issues/5977)) ([a1b1346](https://github.com/noir-lang/noir/commit/a1b1346bf7525c508fd390393c307475cc2345d7)) +* Take blackbox function outputs into account when merging expressions ([#6532](https://github.com/noir-lang/noir/issues/6532)) ([713df69](https://github.com/noir-lang/noir/commit/713df69aad56fc5aaefd5d140275a3217de4d866)) +* **tests:** Prevent EOF error while running test programs ([#6455](https://github.com/noir-lang/noir/issues/6455)) ([358e381](https://github.com/noir-lang/noir/commit/358e38107edbc4f40c97b88196456d82f5557e3f)) +* Typing of artifacts (https://github.com/AztecProtocol/aztec-packages/pull/9581) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) + + +### Miscellaneous Chores + +* Remove `recursive` from ACIR format; add them to API and CLI (https://github.com/AztecProtocol/aztec-packages/pull/9479) ([7dd71c1](https://github.com/noir-lang/noir/commit/7dd71c15cbcbf025ba049b506c94924903b32754)) +* Remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove noir_js_backend_barretenberg (https://github.com/AztecProtocol/aztec-packages/pull/9338) ([3925228](https://github.com/noir-lang/noir/commit/392522880e102e275ebcf42f16651a8ffa0bbbd2)) +* Remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Replace usage of vector in keccakf1600 input with array (https://github.com/AztecProtocol/aztec-packages/pull/9350) ([3925228](https://github.com/noir-lang/noir/commit/392522880e102e275ebcf42f16651a8ffa0bbbd2)) +* Use Brillig opcode when possible for less-than operations on fields (https://github.com/AztecProtocol/aztec-packages/pull/9416) ([321a493](https://github.com/noir-lang/noir/commit/321a493216e19a2f077007c3447a3030db0df0d0)) + + +### Code Refactoring + +* **avm:** Remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) + +## [0.54.0](https://github.com/noir-lang/noir/compare/v0.53.0...v0.54.0) (2024-11-08) + + +### ⚠ BREAKING CHANGES + +* **avm/brillig:** revert/rethrow oracle (https://github.com/AztecProtocol/aztec-packages/pull/9408) +* use Brillig opcode when possible for less-than operations on fields (https://github.com/AztecProtocol/aztec-packages/pull/9416) +* remove noir_js_backend_barretenberg (https://github.com/AztecProtocol/aztec-packages/pull/9338) +* replace usage of vector in keccakf1600 input with array (https://github.com/AztecProtocol/aztec-packages/pull/9350) +* **profiler:** New flamegraph command that profiles the opcodes executed ([#6327](https://github.com/noir-lang/noir/issues/6327)) +* remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) +* remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) +* remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) +* **avm:** remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) +* remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) +* add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) +* **avm:** variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) +* **avm/brillig:** take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) + +### Features + +* (bb) 128-bit challenges (https://github.com/AztecProtocol/aztec-packages/pull/8406) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **acir_gen:** Width aware ACIR gen addition ([#5493](https://github.com/noir-lang/noir/issues/5493)) ([85fa592](https://github.com/noir-lang/noir/commit/85fa592fdef3b8589ce03b232e1b51565837b540)) +* Add assertions for ACVM `FunctionInput` `bit_size` ([#5864](https://github.com/noir-lang/noir/issues/5864)) ([8712f4c](https://github.com/noir-lang/noir/commit/8712f4c20d23f3809bcfb03f2e3ba0e5ace20a1d)) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Add recursive aggregation object to proving/verification keys (https://github.com/AztecProtocol/aztec-packages/pull/6770) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Add reusable procedures to brillig generation (https://github.com/AztecProtocol/aztec-packages/pull/7981) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Added indirect const instruction (https://github.com/AztecProtocol/aztec-packages/pull/8065) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Adding aggregation to honk and rollup (https://github.com/AztecProtocol/aztec-packages/pull/7466) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Automate verify_honk_proof input generation (https://github.com/AztecProtocol/aztec-packages/pull/8092) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **avm/brillig:** Revert/rethrow oracle (https://github.com/AztecProtocol/aztec-packages/pull/9408) ([321a493](https://github.com/noir-lang/noir/commit/321a493216e19a2f077007c3447a3030db0df0d0)) +* **avm/brillig:** Take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **avm:** Variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Avoid heap allocs when going to/from field (https://github.com/AztecProtocol/aztec-packages/pull/7547) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Change the layout of arrays and vectors to be a single pointer (https://github.com/AztecProtocol/aztec-packages/pull/8448) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Ensure that generated ACIR is solvable ([#6415](https://github.com/noir-lang/noir/issues/6415)) ([b473d99](https://github.com/noir-lang/noir/commit/b473d99b2b70b595596b8392617256dbaf5d5642)) +* Hook up secondary calldata column in dsl (https://github.com/AztecProtocol/aztec-packages/pull/7759) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Integrate databus in the private kernels (https://github.com/AztecProtocol/aztec-packages/pull/9028) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Integrate new proving systems in e2e (https://github.com/AztecProtocol/aztec-packages/pull/6971) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Make Brillig do integer arithmetic operations using u128 instead of Bigint (https://github.com/AztecProtocol/aztec-packages/pull/7518) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Make token transfer be recursive (https://github.com/AztecProtocol/aztec-packages/pull/7730) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* New test programs for wasm benchmarking (https://github.com/AztecProtocol/aztec-packages/pull/8389) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Note hashes as points (https://github.com/AztecProtocol/aztec-packages/pull/7618) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize allocating immediate amounts of memory (https://github.com/AztecProtocol/aztec-packages/pull/8579) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Optimize constant array handling in brillig_gen (https://github.com/AztecProtocol/aztec-packages/pull/7661) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize to_radix (https://github.com/AztecProtocol/aztec-packages/pull/8073) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Pass calldata ids to the backend (https://github.com/AztecProtocol/aztec-packages/pull/7875) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Poseidon2 gates for Ultra arithmetisation (https://github.com/AztecProtocol/aztec-packages/pull/7494) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **profiler:** Add support for brillig functions in opcodes-flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7698) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* **profiler:** New flamegraph command that profiles the opcodes executed ([#6327](https://github.com/noir-lang/noir/issues/6327)) ([4d87c9a](https://github.com/noir-lang/noir/commit/4d87c9ac78b48b4bd0ae81316df28aab390d004e)) +* Remove 'single use' intermediate variables ([#6268](https://github.com/noir-lang/noir/issues/6268)) ([ec75e8e](https://github.com/noir-lang/noir/commit/ec75e8ec59e0f2a2169aea67372411ede4074d09)) +* Remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Removing superfluous call to MSM (https://github.com/AztecProtocol/aztec-packages/pull/7708) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Report gates and VKs of private protocol circuits with megahonk (https://github.com/AztecProtocol/aztec-packages/pull/7722) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Simplify constant calls to `poseidon2_permutation`, `schnorr_verify` and `embedded_curve_add` ([#5140](https://github.com/noir-lang/noir/issues/5140)) ([2823ba7](https://github.com/noir-lang/noir/commit/2823ba7242db788ca1d7f6e7a48be2f1de62f278)) +* Small optimization in toradix (https://github.com/AztecProtocol/aztec-packages/pull/8040) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7432) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7444) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7454) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7512) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7577) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7583) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7743) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7862) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7945) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7958) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8008) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8093) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8125) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8237) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8423) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8435) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8466) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8482) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8512) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8526) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8934) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9034) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9099) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9275) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* **test:** Fuzz test poseidon2 hash equivalence ([#6265](https://github.com/noir-lang/noir/issues/6265)) ([f61ba03](https://github.com/noir-lang/noir/commit/f61ba037c6726e19be4f894d9447fe396df95417)) +* **test:** Fuzz test stdlib hash functions ([#6233](https://github.com/noir-lang/noir/issues/6233)) ([1a2ca46](https://github.com/noir-lang/noir/commit/1a2ca46af0d1c05813dbe28670a2bc39b79e4c9f)) +* TXE nr deployments, dependency cleanup for CLI (https://github.com/AztecProtocol/aztec-packages/pull/7548) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Typing return values of embedded_curve_ops (https://github.com/AztecProtocol/aztec-packages/pull/7413) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Unify all acir recursion constraints based on RecursionConstraint and proof_type (https://github.com/AztecProtocol/aztec-packages/pull/7993) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) + + +### Bug Fixes + +* Add trailing extra arguments for backend in gates_flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7472) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* **debugger:** Update the debugger to handle the new Brillig debug metadata format ([#5706](https://github.com/noir-lang/noir/issues/5706)) ([a31f82e](https://github.com/noir-lang/noir/commit/a31f82e598def60d00c65b79b8c5411f8aa832aa)) +* Deflatten databus visibilities (https://github.com/AztecProtocol/aztec-packages/pull/7761) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Discard optimisation that would change execution ordering or that is related to call outputs ([#6461](https://github.com/noir-lang/noir/issues/6461)) ([b8654f7](https://github.com/noir-lang/noir/commit/b8654f700b218cc09c5381af65df11ead9ffcdaf)) +* Display every bit in integer tokens ([#6360](https://github.com/noir-lang/noir/issues/6360)) ([b985fdf](https://github.com/noir-lang/noir/commit/b985fdf6e635570b8db3af83d9ec14e7cd749062)) +* Do not duplicate redundant Brillig debug metadata ([#5696](https://github.com/noir-lang/noir/issues/5696)) ([e4f7dbe](https://github.com/noir-lang/noir/commit/e4f7dbe63b55807b3ff0b4d6f47a8b7f847299fb)) +* Export brillig names in contract functions (https://github.com/AztecProtocol/aztec-packages/pull/8212) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Handle multiple entry points for Brillig call stack resolution after metadata deduplication ([#5788](https://github.com/noir-lang/noir/issues/5788)) ([38fe9dd](https://github.com/noir-lang/noir/commit/38fe9dda111952fdb894df90a319c087382edfc9)) +* Homogeneous input points for EC ADD ([#6241](https://github.com/noir-lang/noir/issues/6241)) ([f6a7306](https://github.com/noir-lang/noir/commit/f6a7306436ea1a37ec7f3b884721b50467e9a063)) +* Reject invalid expression with in CLI parser ([#6287](https://github.com/noir-lang/noir/issues/6287)) ([052aee8](https://github.com/noir-lang/noir/commit/052aee80ff3e1e4fd2ca45310d7bb8b980af126a)) +* Remove need for duplicate attributes on each function (https://github.com/AztecProtocol/aztec-packages/pull/9244) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Restrict keccak256_injective test input to 8 bits ([#5977](https://github.com/noir-lang/noir/issues/5977)) ([a1b1346](https://github.com/noir-lang/noir/commit/a1b1346bf7525c508fd390393c307475cc2345d7)) +* Revert "feat: Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7512)" (https://github.com/AztecProtocol/aztec-packages/pull/7558) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* **tests:** Prevent EOF error while running test programs ([#6455](https://github.com/noir-lang/noir/issues/6455)) ([358e381](https://github.com/noir-lang/noir/commit/358e38107edbc4f40c97b88196456d82f5557e3f)) + + +### Miscellaneous Chores + +* Remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove noir_js_backend_barretenberg (https://github.com/AztecProtocol/aztec-packages/pull/9338) ([3925228](https://github.com/noir-lang/noir/commit/392522880e102e275ebcf42f16651a8ffa0bbbd2)) +* Remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Replace usage of vector in keccakf1600 input with array (https://github.com/AztecProtocol/aztec-packages/pull/9350) ([3925228](https://github.com/noir-lang/noir/commit/392522880e102e275ebcf42f16651a8ffa0bbbd2)) +* Use Brillig opcode when possible for less-than operations on fields (https://github.com/AztecProtocol/aztec-packages/pull/9416) ([321a493](https://github.com/noir-lang/noir/commit/321a493216e19a2f077007c3447a3030db0df0d0)) + + +### Code Refactoring + +* **avm:** Remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) + +## [0.53.0](https://github.com/noir-lang/noir/compare/v0.52.0...v0.53.0) (2024-10-31) + + +### ⚠ BREAKING CHANGES + +* **avm/brillig:** revert/rethrow oracle (https://github.com/AztecProtocol/aztec-packages/pull/9408) +* use Brillig opcode when possible for less-than operations on fields (https://github.com/AztecProtocol/aztec-packages/pull/9416) +* remove noir_js_backend_barretenberg (https://github.com/AztecProtocol/aztec-packages/pull/9338) +* replace usage of vector in keccakf1600 input with array (https://github.com/AztecProtocol/aztec-packages/pull/9350) +* **profiler:** New flamegraph command that profiles the opcodes executed ([#6327](https://github.com/noir-lang/noir/issues/6327)) +* remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) +* remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) +* remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) +* **avm:** remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) +* remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) +* add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) +* **avm:** variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) +* **avm/brillig:** take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) + +### Features + +* (bb) 128-bit challenges (https://github.com/AztecProtocol/aztec-packages/pull/8406) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **acir_gen:** Width aware ACIR gen addition ([#5493](https://github.com/noir-lang/noir/issues/5493)) ([85fa592](https://github.com/noir-lang/noir/commit/85fa592fdef3b8589ce03b232e1b51565837b540)) +* Add assertions for ACVM `FunctionInput` `bit_size` ([#5864](https://github.com/noir-lang/noir/issues/5864)) ([8712f4c](https://github.com/noir-lang/noir/commit/8712f4c20d23f3809bcfb03f2e3ba0e5ace20a1d)) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Add recursive aggregation object to proving/verification keys (https://github.com/AztecProtocol/aztec-packages/pull/6770) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Add reusable procedures to brillig generation (https://github.com/AztecProtocol/aztec-packages/pull/7981) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Added indirect const instruction (https://github.com/AztecProtocol/aztec-packages/pull/8065) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Adding aggregation to honk and rollup (https://github.com/AztecProtocol/aztec-packages/pull/7466) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Automate verify_honk_proof input generation (https://github.com/AztecProtocol/aztec-packages/pull/8092) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **avm/brillig:** Revert/rethrow oracle (https://github.com/AztecProtocol/aztec-packages/pull/9408) ([321a493](https://github.com/noir-lang/noir/commit/321a493216e19a2f077007c3447a3030db0df0d0)) +* **avm/brillig:** Take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **avm:** Variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Avoid heap allocs when going to/from field (https://github.com/AztecProtocol/aztec-packages/pull/7547) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Change the layout of arrays and vectors to be a single pointer (https://github.com/AztecProtocol/aztec-packages/pull/8448) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Hook up secondary calldata column in dsl (https://github.com/AztecProtocol/aztec-packages/pull/7759) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Integrate databus in the private kernels (https://github.com/AztecProtocol/aztec-packages/pull/9028) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Integrate new proving systems in e2e (https://github.com/AztecProtocol/aztec-packages/pull/6971) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Make Brillig do integer arithmetic operations using u128 instead of Bigint (https://github.com/AztecProtocol/aztec-packages/pull/7518) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Make token transfer be recursive (https://github.com/AztecProtocol/aztec-packages/pull/7730) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* New test programs for wasm benchmarking (https://github.com/AztecProtocol/aztec-packages/pull/8389) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Note hashes as points (https://github.com/AztecProtocol/aztec-packages/pull/7618) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize allocating immediate amounts of memory (https://github.com/AztecProtocol/aztec-packages/pull/8579) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Optimize constant array handling in brillig_gen (https://github.com/AztecProtocol/aztec-packages/pull/7661) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize to_radix (https://github.com/AztecProtocol/aztec-packages/pull/8073) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Pass calldata ids to the backend (https://github.com/AztecProtocol/aztec-packages/pull/7875) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Poseidon2 gates for Ultra arithmetisation (https://github.com/AztecProtocol/aztec-packages/pull/7494) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **profiler:** Add support for brillig functions in opcodes-flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7698) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* **profiler:** New flamegraph command that profiles the opcodes executed ([#6327](https://github.com/noir-lang/noir/issues/6327)) ([4d87c9a](https://github.com/noir-lang/noir/commit/4d87c9ac78b48b4bd0ae81316df28aab390d004e)) +* Remove 'single use' intermediate variables ([#6268](https://github.com/noir-lang/noir/issues/6268)) ([ec75e8e](https://github.com/noir-lang/noir/commit/ec75e8ec59e0f2a2169aea67372411ede4074d09)) +* Remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Removing superfluous call to MSM (https://github.com/AztecProtocol/aztec-packages/pull/7708) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Report gates and VKs of private protocol circuits with megahonk (https://github.com/AztecProtocol/aztec-packages/pull/7722) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Simplify constant calls to `poseidon2_permutation`, `schnorr_verify` and `embedded_curve_add` ([#5140](https://github.com/noir-lang/noir/issues/5140)) ([2823ba7](https://github.com/noir-lang/noir/commit/2823ba7242db788ca1d7f6e7a48be2f1de62f278)) +* Small optimization in toradix (https://github.com/AztecProtocol/aztec-packages/pull/8040) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7432) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7444) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7454) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7512) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7577) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7583) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7743) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7862) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7945) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7958) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8008) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8093) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8125) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8237) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8423) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8435) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8466) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8482) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8512) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8526) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8934) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9034) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9099) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9275) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* **test:** Fuzz test poseidon2 hash equivalence ([#6265](https://github.com/noir-lang/noir/issues/6265)) ([f61ba03](https://github.com/noir-lang/noir/commit/f61ba037c6726e19be4f894d9447fe396df95417)) +* **test:** Fuzz test stdlib hash functions ([#6233](https://github.com/noir-lang/noir/issues/6233)) ([1a2ca46](https://github.com/noir-lang/noir/commit/1a2ca46af0d1c05813dbe28670a2bc39b79e4c9f)) +* TXE nr deployments, dependency cleanup for CLI (https://github.com/AztecProtocol/aztec-packages/pull/7548) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Typing return values of embedded_curve_ops (https://github.com/AztecProtocol/aztec-packages/pull/7413) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Unify all acir recursion constraints based on RecursionConstraint and proof_type (https://github.com/AztecProtocol/aztec-packages/pull/7993) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) + + +### Bug Fixes + +* Add trailing extra arguments for backend in gates_flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7472) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* **debugger:** Update the debugger to handle the new Brillig debug metadata format ([#5706](https://github.com/noir-lang/noir/issues/5706)) ([a31f82e](https://github.com/noir-lang/noir/commit/a31f82e598def60d00c65b79b8c5411f8aa832aa)) +* Deflatten databus visibilities (https://github.com/AztecProtocol/aztec-packages/pull/7761) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Display every bit in integer tokens ([#6360](https://github.com/noir-lang/noir/issues/6360)) ([b985fdf](https://github.com/noir-lang/noir/commit/b985fdf6e635570b8db3af83d9ec14e7cd749062)) +* Do not duplicate redundant Brillig debug metadata ([#5696](https://github.com/noir-lang/noir/issues/5696)) ([e4f7dbe](https://github.com/noir-lang/noir/commit/e4f7dbe63b55807b3ff0b4d6f47a8b7f847299fb)) +* Export brillig names in contract functions (https://github.com/AztecProtocol/aztec-packages/pull/8212) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Handle multiple entry points for Brillig call stack resolution after metadata deduplication ([#5788](https://github.com/noir-lang/noir/issues/5788)) ([38fe9dd](https://github.com/noir-lang/noir/commit/38fe9dda111952fdb894df90a319c087382edfc9)) +* Homogeneous input points for EC ADD ([#6241](https://github.com/noir-lang/noir/issues/6241)) ([f6a7306](https://github.com/noir-lang/noir/commit/f6a7306436ea1a37ec7f3b884721b50467e9a063)) +* Reject invalid expression with in CLI parser ([#6287](https://github.com/noir-lang/noir/issues/6287)) ([052aee8](https://github.com/noir-lang/noir/commit/052aee80ff3e1e4fd2ca45310d7bb8b980af126a)) +* Remove need for duplicate attributes on each function (https://github.com/AztecProtocol/aztec-packages/pull/9244) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Restrict keccak256_injective test input to 8 bits ([#5977](https://github.com/noir-lang/noir/issues/5977)) ([a1b1346](https://github.com/noir-lang/noir/commit/a1b1346bf7525c508fd390393c307475cc2345d7)) +* Revert "feat: Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7512)" (https://github.com/AztecProtocol/aztec-packages/pull/7558) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) + + +### Miscellaneous Chores + +* Remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove noir_js_backend_barretenberg (https://github.com/AztecProtocol/aztec-packages/pull/9338) ([3925228](https://github.com/noir-lang/noir/commit/392522880e102e275ebcf42f16651a8ffa0bbbd2)) +* Remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Replace usage of vector in keccakf1600 input with array (https://github.com/AztecProtocol/aztec-packages/pull/9350) ([3925228](https://github.com/noir-lang/noir/commit/392522880e102e275ebcf42f16651a8ffa0bbbd2)) +* Use Brillig opcode when possible for less-than operations on fields (https://github.com/AztecProtocol/aztec-packages/pull/9416) ([321a493](https://github.com/noir-lang/noir/commit/321a493216e19a2f077007c3447a3030db0df0d0)) + + +### Code Refactoring + +* **avm:** Remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) + +## [0.52.0](https://github.com/noir-lang/noir/compare/v0.51.0...v0.52.0) (2024-10-22) + + +### ⚠ BREAKING CHANGES + +* remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) +* remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) +* remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) +* **avm:** remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) +* remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) +* add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) +* **avm:** variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) +* **avm/brillig:** take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) +* constant inputs for blackbox (https://github.com/AztecProtocol/aztec-packages/pull/7222) + +### Features + +* (bb) 128-bit challenges (https://github.com/AztecProtocol/aztec-packages/pull/8406) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **acir_gen:** Width aware ACIR gen addition ([#5493](https://github.com/noir-lang/noir/issues/5493)) ([85fa592](https://github.com/noir-lang/noir/commit/85fa592fdef3b8589ce03b232e1b51565837b540)) +* Add assertions for ACVM `FunctionInput` `bit_size` ([#5864](https://github.com/noir-lang/noir/issues/5864)) ([8712f4c](https://github.com/noir-lang/noir/commit/8712f4c20d23f3809bcfb03f2e3ba0e5ace20a1d)) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Add recursive aggregation object to proving/verification keys (https://github.com/AztecProtocol/aztec-packages/pull/6770) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Add reusable procedures to brillig generation (https://github.com/AztecProtocol/aztec-packages/pull/7981) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Added indirect const instruction (https://github.com/AztecProtocol/aztec-packages/pull/8065) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Adding aggregation to honk and rollup (https://github.com/AztecProtocol/aztec-packages/pull/7466) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Automate verify_honk_proof input generation (https://github.com/AztecProtocol/aztec-packages/pull/8092) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **avm/brillig:** Take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **avm:** Variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Avoid heap allocs when going to/from field (https://github.com/AztecProtocol/aztec-packages/pull/7547) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Change the layout of arrays and vectors to be a single pointer (https://github.com/AztecProtocol/aztec-packages/pull/8448) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Constant inputs for blackbox (https://github.com/AztecProtocol/aztec-packages/pull/7222) ([fb97bb9](https://github.com/noir-lang/noir/commit/fb97bb9b795c9d7af395b82fd6f0ea8111d59c11)) +* Hook up secondary calldata column in dsl (https://github.com/AztecProtocol/aztec-packages/pull/7759) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Integrate databus in the private kernels (https://github.com/AztecProtocol/aztec-packages/pull/9028) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Integrate new proving systems in e2e (https://github.com/AztecProtocol/aztec-packages/pull/6971) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Make Brillig do integer arithmetic operations using u128 instead of Bigint (https://github.com/AztecProtocol/aztec-packages/pull/7518) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Make token transfer be recursive (https://github.com/AztecProtocol/aztec-packages/pull/7730) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* New test programs for wasm benchmarking (https://github.com/AztecProtocol/aztec-packages/pull/8389) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Note hashes as points (https://github.com/AztecProtocol/aztec-packages/pull/7618) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize allocating immediate amounts of memory (https://github.com/AztecProtocol/aztec-packages/pull/8579) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Optimize constant array handling in brillig_gen (https://github.com/AztecProtocol/aztec-packages/pull/7661) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize to_radix (https://github.com/AztecProtocol/aztec-packages/pull/8073) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Pass calldata ids to the backend (https://github.com/AztecProtocol/aztec-packages/pull/7875) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Poseidon2 gates for Ultra arithmetisation (https://github.com/AztecProtocol/aztec-packages/pull/7494) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **profiler:** Add support for brillig functions in opcodes-flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7698) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Removing superfluous call to MSM (https://github.com/AztecProtocol/aztec-packages/pull/7708) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Report gates and VKs of private protocol circuits with megahonk (https://github.com/AztecProtocol/aztec-packages/pull/7722) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Simplify constant calls to `poseidon2_permutation`, `schnorr_verify` and `embedded_curve_add` ([#5140](https://github.com/noir-lang/noir/issues/5140)) ([2823ba7](https://github.com/noir-lang/noir/commit/2823ba7242db788ca1d7f6e7a48be2f1de62f278)) +* Small optimization in toradix (https://github.com/AztecProtocol/aztec-packages/pull/8040) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7392) ([fb97bb9](https://github.com/noir-lang/noir/commit/fb97bb9b795c9d7af395b82fd6f0ea8111d59c11)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7400) ([fb97bb9](https://github.com/noir-lang/noir/commit/fb97bb9b795c9d7af395b82fd6f0ea8111d59c11)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7432) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7444) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7454) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7512) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7577) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7583) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7743) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7862) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7945) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7958) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8008) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8093) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8125) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8237) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8423) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8435) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8466) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8482) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8512) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8526) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8934) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9034) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9099) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9275) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* **test:** Fuzz test poseidon2 hash equivalence ([#6265](https://github.com/noir-lang/noir/issues/6265)) ([f61ba03](https://github.com/noir-lang/noir/commit/f61ba037c6726e19be4f894d9447fe396df95417)) +* **test:** Fuzz test stdlib hash functions ([#6233](https://github.com/noir-lang/noir/issues/6233)) ([1a2ca46](https://github.com/noir-lang/noir/commit/1a2ca46af0d1c05813dbe28670a2bc39b79e4c9f)) +* TXE nr deployments, dependency cleanup for CLI (https://github.com/AztecProtocol/aztec-packages/pull/7548) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Typing return values of embedded_curve_ops (https://github.com/AztecProtocol/aztec-packages/pull/7413) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Unify all acir recursion constraints based on RecursionConstraint and proof_type (https://github.com/AztecProtocol/aztec-packages/pull/7993) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) + + +### Bug Fixes + +* Add trailing extra arguments for backend in gates_flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7472) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* **debugger:** Update the debugger to handle the new Brillig debug metadata format ([#5706](https://github.com/noir-lang/noir/issues/5706)) ([a31f82e](https://github.com/noir-lang/noir/commit/a31f82e598def60d00c65b79b8c5411f8aa832aa)) +* Deflatten databus visibilities (https://github.com/AztecProtocol/aztec-packages/pull/7761) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Do not duplicate redundant Brillig debug metadata ([#5696](https://github.com/noir-lang/noir/issues/5696)) ([e4f7dbe](https://github.com/noir-lang/noir/commit/e4f7dbe63b55807b3ff0b4d6f47a8b7f847299fb)) +* Export brillig names in contract functions (https://github.com/AztecProtocol/aztec-packages/pull/8212) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Handle multiple entry points for Brillig call stack resolution after metadata deduplication ([#5788](https://github.com/noir-lang/noir/issues/5788)) ([38fe9dd](https://github.com/noir-lang/noir/commit/38fe9dda111952fdb894df90a319c087382edfc9)) +* Homogeneous input points for EC ADD ([#6241](https://github.com/noir-lang/noir/issues/6241)) ([f6a7306](https://github.com/noir-lang/noir/commit/f6a7306436ea1a37ec7f3b884721b50467e9a063)) +* Move BigInt modulus checks to runtime in brillig ([#5374](https://github.com/noir-lang/noir/issues/5374)) ([741d339](https://github.com/noir-lang/noir/commit/741d33991f8e2918bf092c354ca56047e0274533)) +* Reject invalid expression with in CLI parser ([#6287](https://github.com/noir-lang/noir/issues/6287)) ([052aee8](https://github.com/noir-lang/noir/commit/052aee80ff3e1e4fd2ca45310d7bb8b980af126a)) +* Remove need for duplicate attributes on each function (https://github.com/AztecProtocol/aztec-packages/pull/9244) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Restrict keccak256_injective test input to 8 bits ([#5977](https://github.com/noir-lang/noir/issues/5977)) ([a1b1346](https://github.com/noir-lang/noir/commit/a1b1346bf7525c508fd390393c307475cc2345d7)) +* Revert "feat: Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7512)" (https://github.com/AztecProtocol/aztec-packages/pull/7558) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) + + +### Miscellaneous Chores + +* Remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) + + +### Code Refactoring + +* **avm:** Remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) + +## [0.51.0](https://github.com/noir-lang/noir/compare/v0.50.0...v0.51.0) (2024-10-03) + + +### ⚠ BREAKING CHANGES + +* remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) +* add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) +* **avm:** variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) +* **avm/brillig:** take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) +* constant inputs for blackbox (https://github.com/AztecProtocol/aztec-packages/pull/7222) + +### Features + +* (bb) 128-bit challenges (https://github.com/AztecProtocol/aztec-packages/pull/8406) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **acir_gen:** Width aware ACIR gen addition ([#5493](https://github.com/noir-lang/noir/issues/5493)) ([85fa592](https://github.com/noir-lang/noir/commit/85fa592fdef3b8589ce03b232e1b51565837b540)) +* Add assertions for ACVM `FunctionInput` `bit_size` ([#5864](https://github.com/noir-lang/noir/issues/5864)) ([8712f4c](https://github.com/noir-lang/noir/commit/8712f4c20d23f3809bcfb03f2e3ba0e5ace20a1d)) +* Add Not instruction in brillig (https://github.com/AztecProtocol/aztec-packages/pull/8488) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Add recursive aggregation object to proving/verification keys (https://github.com/AztecProtocol/aztec-packages/pull/6770) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Add reusable procedures to brillig generation (https://github.com/AztecProtocol/aztec-packages/pull/7981) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Added indirect const instruction (https://github.com/AztecProtocol/aztec-packages/pull/8065) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Adding aggregation to honk and rollup (https://github.com/AztecProtocol/aztec-packages/pull/7466) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Automate verify_honk_proof input generation (https://github.com/AztecProtocol/aztec-packages/pull/8092) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **avm/brillig:** Take addresses in calldatacopy (https://github.com/AztecProtocol/aztec-packages/pull/8388) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* **avm:** Variants for SET opcode (https://github.com/AztecProtocol/aztec-packages/pull/8441) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Avoid heap allocs when going to/from field (https://github.com/AztecProtocol/aztec-packages/pull/7547) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Change the layout of arrays and vectors to be a single pointer (https://github.com/AztecProtocol/aztec-packages/pull/8448) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Constant inputs for blackbox (https://github.com/AztecProtocol/aztec-packages/pull/7222) ([fb97bb9](https://github.com/noir-lang/noir/commit/fb97bb9b795c9d7af395b82fd6f0ea8111d59c11)) +* Hook up secondary calldata column in dsl (https://github.com/AztecProtocol/aztec-packages/pull/7759) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Integrate new proving systems in e2e (https://github.com/AztecProtocol/aztec-packages/pull/6971) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Make Brillig do integer arithmetic operations using u128 instead of Bigint (https://github.com/AztecProtocol/aztec-packages/pull/7518) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Make token transfer be recursive (https://github.com/AztecProtocol/aztec-packages/pull/7730) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* New test programs for wasm benchmarking (https://github.com/AztecProtocol/aztec-packages/pull/8389) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Note hashes as points (https://github.com/AztecProtocol/aztec-packages/pull/7618) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize allocating immediate amounts of memory (https://github.com/AztecProtocol/aztec-packages/pull/8579) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Optimize constant array handling in brillig_gen (https://github.com/AztecProtocol/aztec-packages/pull/7661) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Optimize to_radix (https://github.com/AztecProtocol/aztec-packages/pull/8073) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Pass calldata ids to the backend (https://github.com/AztecProtocol/aztec-packages/pull/7875) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Poseidon2 gates for Ultra arithmetisation (https://github.com/AztecProtocol/aztec-packages/pull/7494) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* **profiler:** Add support for brillig functions in opcodes-flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7698) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* Removing superfluous call to MSM (https://github.com/AztecProtocol/aztec-packages/pull/7708) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Report gates and VKs of private protocol circuits with megahonk (https://github.com/AztecProtocol/aztec-packages/pull/7722) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Simplify constant calls to `poseidon2_permutation`, `schnorr_verify` and `embedded_curve_add` ([#5140](https://github.com/noir-lang/noir/issues/5140)) ([2823ba7](https://github.com/noir-lang/noir/commit/2823ba7242db788ca1d7f6e7a48be2f1de62f278)) +* Small optimization in toradix (https://github.com/AztecProtocol/aztec-packages/pull/8040) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7392) ([fb97bb9](https://github.com/noir-lang/noir/commit/fb97bb9b795c9d7af395b82fd6f0ea8111d59c11)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7400) ([fb97bb9](https://github.com/noir-lang/noir/commit/fb97bb9b795c9d7af395b82fd6f0ea8111d59c11)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7432) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7444) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7454) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7512) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7577) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7583) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7743) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7862) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7945) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7958) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8008) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8093) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8125) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8237) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8423) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8435) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8466) ([3c3ed1e](https://github.com/noir-lang/noir/commit/3c3ed1e3d28946a02071c524dd128afe131bc3da)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8482) ([d4832ec](https://github.com/noir-lang/noir/commit/d4832ece9d3ad16544afea49cc7caf40501a2cc3)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8512) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8526) ([95e19ab](https://github.com/noir-lang/noir/commit/95e19ab9486ad054241b6e53e40e55bdba9dc7e5)) +* TXE nr deployments, dependency cleanup for CLI (https://github.com/AztecProtocol/aztec-packages/pull/7548) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Typing return values of embedded_curve_ops (https://github.com/AztecProtocol/aztec-packages/pull/7413) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Unify all acir recursion constraints based on RecursionConstraint and proof_type (https://github.com/AztecProtocol/aztec-packages/pull/7993) ([5c4f19f](https://github.com/noir-lang/noir/commit/5c4f19f097dd3704522996330c961bf0a2db8d99)) + + +### Bug Fixes + +* Add trailing extra arguments for backend in gates_flamegraph (https://github.com/AztecProtocol/aztec-packages/pull/7472) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* **debugger:** Update the debugger to handle the new Brillig debug metadata format ([#5706](https://github.com/noir-lang/noir/issues/5706)) ([a31f82e](https://github.com/noir-lang/noir/commit/a31f82e598def60d00c65b79b8c5411f8aa832aa)) +* Deflatten databus visibilities (https://github.com/AztecProtocol/aztec-packages/pull/7761) ([4ea25db](https://github.com/noir-lang/noir/commit/4ea25dbde87488e758139619a3ce4edf93c6ebd6)) +* Do not duplicate redundant Brillig debug metadata ([#5696](https://github.com/noir-lang/noir/issues/5696)) ([e4f7dbe](https://github.com/noir-lang/noir/commit/e4f7dbe63b55807b3ff0b4d6f47a8b7f847299fb)) +* Export brillig names in contract functions (https://github.com/AztecProtocol/aztec-packages/pull/8212) ([f0c2686](https://github.com/noir-lang/noir/commit/f0c268606a71381ab4504396695a0adb9b3258b6)) +* Handle multiple entry points for Brillig call stack resolution after metadata deduplication ([#5788](https://github.com/noir-lang/noir/issues/5788)) ([38fe9dd](https://github.com/noir-lang/noir/commit/38fe9dda111952fdb894df90a319c087382edfc9)) +* Move BigInt modulus checks to runtime in brillig ([#5374](https://github.com/noir-lang/noir/issues/5374)) ([741d339](https://github.com/noir-lang/noir/commit/741d33991f8e2918bf092c354ca56047e0274533)) +* Restrict keccak256_injective test input to 8 bits ([#5977](https://github.com/noir-lang/noir/issues/5977)) ([a1b1346](https://github.com/noir-lang/noir/commit/a1b1346bf7525c508fd390393c307475cc2345d7)) +* Revert "feat: Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/7512)" (https://github.com/AztecProtocol/aztec-packages/pull/7558) ([daad75c](https://github.com/noir-lang/noir/commit/daad75c26d19ae707b90a7424b77dab9937e8575)) +* Runtime brillig bigint id assignment ([#5369](https://github.com/noir-lang/noir/issues/5369)) ([a8928dd](https://github.com/noir-lang/noir/commit/a8928ddcffcae15babf7aa5aff0e462e4549552e)) + ## [0.50.0](https://github.com/noir-lang/noir/compare/v0.49.0...v0.50.0) (2024-09-13) diff --git a/acvm-repo/acir/Cargo.toml b/acvm-repo/acir/Cargo.toml index b707ae9ad79..8139a58eefc 100644 --- a/acvm-repo/acir/Cargo.toml +++ b/acvm-repo/acir/Cargo.toml @@ -2,7 +2,7 @@ name = "acir" description = "ACIR is the IR that the VM processes, it is analogous to LLVM IR" # x-release-please-start-version -version = "0.50.0" +version = "1.0.0-beta.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -24,11 +24,11 @@ flate2.workspace = true bincode.workspace = true base64.workspace = true serde-big-array = "0.5.1" +strum = { workspace = true } +strum_macros = { workspace = true } [dev-dependencies] serde_json = "1.0" -strum = "0.24" -strum_macros = "0.24" serde-reflection = "0.3.6" serde-generate = "0.25.1" fxhash.workspace = true diff --git a/acvm-repo/acir/README.md b/acvm-repo/acir/README.md index 902769e3ad7..a0e7094b4d6 100644 --- a/acvm-repo/acir/README.md +++ b/acvm-repo/acir/README.md @@ -77,7 +77,7 @@ In summary, the workflow is the following: 1. user program -> (compilation) ACIR, a list of opcodes which constrain (partial) witnesses 2. user inputs + ACIR -> (execution/solving) assign values to all the - (partial) witnesses + (partial) witnesses 3. witness assignment + ACIR -> (proving system) proof Although the ordering of opcode does not matter in theory, since a system of @@ -121,7 +121,7 @@ proving system and are only used by the solver. Finally, some opcodes will have a predicate, whose value is `0` or `1`. Its purpose is to nullify the opcode when the value is `0`, so that it has no effect. Note that removing the opcode is not a solution because this modifies -the circuit (the circuit being mainly the list of the opcodes). +the circuit (the circuit being mainly the list of the opcodes). *Remark*: Opcodes operate on witnesses, but we will see that some opcode work on expressions of witnesses. We call an expression a linear combination of @@ -265,16 +265,6 @@ without adding any constraint. NOTE: see the [circuit/opcodes.rs](src/circuit/opcodes.rs) file for the most up-to-date documentation on these opcodes. -#### Directive - -This opcode is a specialization of Brillig opcode. Instead of having some generic -assembly code like Brillig, a directive has a hardcoded name which tells the -solver which computation to do: with Brillig, the computation refers to the -compiled bytecode of an unconstrained Noir function, but with a directive, the -computation is hardcoded inside the compiler. - -Directives will be replaced by Brillig opcodes in the future. - #### MemoryOp: memory abstraction for ACIR ACIR is able to address any array of witnesses. Each array is assigned an ID diff --git a/acvm-repo/acir/benches/serialization.rs b/acvm-repo/acir/benches/serialization.rs index 792200c8912..dd6a5c8b1cf 100644 --- a/acvm-repo/acir/benches/serialization.rs +++ b/acvm-repo/acir/benches/serialization.rs @@ -38,7 +38,6 @@ fn sample_program(num_opcodes: usize) -> Program { public_parameters: PublicInputs(BTreeSet::from([Witness(5)])), return_values: PublicInputs(BTreeSet::from([Witness(6)])), assert_messages: Vec::new(), - recursive: false, }], unconstrained_functions: Vec::new(), } diff --git a/acvm-repo/acir/codegen/acir.cpp b/acvm-repo/acir/codegen/acir.cpp index 70ad596a93a..e94f36535d2 100644 --- a/acvm-repo/acir/codegen/acir.cpp +++ b/acvm-repo/acir/codegen/acir.cpp @@ -145,12 +145,6 @@ namespace Program { struct IntegerBitSize { - struct U0 { - friend bool operator==(const U0&, const U0&); - std::vector bincodeSerialize() const; - static U0 bincodeDeserialize(std::vector); - }; - struct U1 { friend bool operator==(const U1&, const U1&); std::vector bincodeSerialize() const; @@ -187,7 +181,7 @@ namespace Program { static U128 bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const IntegerBitSize&, const IntegerBitSize&); std::vector bincodeSerialize() const; @@ -218,7 +212,24 @@ namespace Program { }; struct MemoryAddress { - uint64_t value; + + struct Direct { + uint64_t value; + + friend bool operator==(const Direct&, const Direct&); + std::vector bincodeSerialize() const; + static Direct bincodeDeserialize(std::vector); + }; + + struct Relative { + uint64_t value; + + friend bool operator==(const Relative&, const Relative&); + std::vector bincodeSerialize() const; + static Relative bincodeDeserialize(std::vector); + }; + + std::variant value; friend bool operator==(const MemoryAddress&, const MemoryAddress&); std::vector bincodeSerialize() const; @@ -274,17 +285,8 @@ namespace Program { static Blake3 bincodeDeserialize(std::vector); }; - struct Keccak256 { - Program::HeapVector message; - Program::HeapArray output; - - friend bool operator==(const Keccak256&, const Keccak256&); - std::vector bincodeSerialize() const; - static Keccak256 bincodeDeserialize(std::vector); - }; - struct Keccakf1600 { - Program::HeapVector message; + Program::HeapArray input; Program::HeapArray output; friend bool operator==(const Keccakf1600&, const Keccakf1600&); @@ -316,38 +318,6 @@ namespace Program { static EcdsaSecp256r1 bincodeDeserialize(std::vector); }; - struct SchnorrVerify { - Program::MemoryAddress public_key_x; - Program::MemoryAddress public_key_y; - Program::HeapVector message; - Program::HeapVector signature; - Program::MemoryAddress result; - - friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); - std::vector bincodeSerialize() const; - static SchnorrVerify bincodeDeserialize(std::vector); - }; - - struct PedersenCommitment { - Program::HeapVector inputs; - Program::MemoryAddress domain_separator; - Program::HeapArray output; - - friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); - std::vector bincodeSerialize() const; - static PedersenCommitment bincodeDeserialize(std::vector); - }; - - struct PedersenHash { - Program::HeapVector inputs; - Program::MemoryAddress domain_separator; - Program::MemoryAddress output; - - friend bool operator==(const PedersenHash&, const PedersenHash&); - std::vector bincodeSerialize() const; - static PedersenHash bincodeDeserialize(std::vector); - }; - struct MultiScalarMul { Program::HeapVector points; Program::HeapVector scalars; @@ -442,8 +412,8 @@ namespace Program { }; struct Sha256Compression { - Program::HeapVector input; - Program::HeapVector hash_values; + Program::HeapArray input; + Program::HeapArray hash_values; Program::HeapArray output; friend bool operator==(const Sha256Compression&, const Sha256Compression&); @@ -462,7 +432,7 @@ namespace Program { static ToRadix bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const BlackBoxOp&, const BlackBoxOp&); std::vector bincodeSerialize() const; @@ -712,7 +682,7 @@ namespace Program { }; struct Trap { - Program::HeapArray revert_data; + Program::HeapVector revert_data; friend bool operator==(const Trap&, const Trap&); std::vector bincodeSerialize() const; @@ -720,8 +690,7 @@ namespace Program { }; struct Stop { - uint64_t return_data_offset; - uint64_t return_data_size; + Program::HeapVector return_data; friend bool operator==(const Stop&, const Stop&); std::vector bincodeSerialize() const; @@ -836,38 +805,6 @@ namespace Program { static Blake3 bincodeDeserialize(std::vector); }; - struct SchnorrVerify { - Program::FunctionInput public_key_x; - Program::FunctionInput public_key_y; - std::array signature; - std::vector message; - Program::Witness output; - - friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); - std::vector bincodeSerialize() const; - static SchnorrVerify bincodeDeserialize(std::vector); - }; - - struct PedersenCommitment { - std::vector inputs; - uint32_t domain_separator; - std::array outputs; - - friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); - std::vector bincodeSerialize() const; - static PedersenCommitment bincodeDeserialize(std::vector); - }; - - struct PedersenHash { - std::vector inputs; - uint32_t domain_separator; - Program::Witness output; - - friend bool operator==(const PedersenHash&, const PedersenHash&); - std::vector bincodeSerialize() const; - static PedersenHash bincodeDeserialize(std::vector); - }; - struct EcdsaSecp256k1 { std::array public_key_x; std::array public_key_y; @@ -912,16 +849,6 @@ namespace Program { static EmbeddedCurveAdd bincodeDeserialize(std::vector); }; - struct Keccak256 { - std::vector inputs; - Program::FunctionInput var_message_size; - std::array outputs; - - friend bool operator==(const Keccak256&, const Keccak256&); - std::vector bincodeSerialize() const; - static Keccak256 bincodeDeserialize(std::vector); - }; - struct Keccakf1600 { std::array inputs; std::array outputs; @@ -1022,7 +949,7 @@ namespace Program { static Sha256Compression bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); std::vector bincodeSerialize() const; @@ -1134,25 +1061,6 @@ namespace Program { static BrilligOutputs bincodeDeserialize(std::vector); }; - struct Directive { - - struct ToLeRadix { - Program::Expression a; - std::vector b; - uint32_t radix; - - friend bool operator==(const ToLeRadix&, const ToLeRadix&); - std::vector bincodeSerialize() const; - static ToLeRadix bincodeDeserialize(std::vector); - }; - - std::variant value; - - friend bool operator==(const Directive&, const Directive&); - std::vector bincodeSerialize() const; - static Directive bincodeDeserialize(std::vector); - }; - struct MemOp { Program::Expression operation; Program::Expression index; @@ -1181,14 +1089,6 @@ namespace Program { static BlackBoxFuncCall bincodeDeserialize(std::vector); }; - struct Directive { - Program::Directive value; - - friend bool operator==(const Directive&, const Directive&); - std::vector bincodeSerialize() const; - static Directive bincodeDeserialize(std::vector); - }; - struct MemoryOp { Program::BlockId block_id; Program::MemOp op; @@ -1231,7 +1131,7 @@ namespace Program { static Call bincodeDeserialize(std::vector); }; - std::variant value; + std::variant value; friend bool operator==(const Opcode&, const Opcode&); std::vector bincodeSerialize() const; @@ -1264,24 +1164,8 @@ namespace Program { }; struct AssertionPayload { - - struct StaticString { - std::string value; - - friend bool operator==(const StaticString&, const StaticString&); - std::vector bincodeSerialize() const; - static StaticString bincodeDeserialize(std::vector); - }; - - struct Dynamic { - std::tuple> value; - - friend bool operator==(const Dynamic&, const Dynamic&); - std::vector bincodeSerialize() const; - static Dynamic bincodeDeserialize(std::vector); - }; - - std::variant value; + uint64_t error_selector; + std::vector payload; friend bool operator==(const AssertionPayload&, const AssertionPayload&); std::vector bincodeSerialize() const; @@ -1353,7 +1237,6 @@ namespace Program { Program::PublicInputs public_parameters; Program::PublicInputs return_values; std::vector> assert_messages; - bool recursive; friend bool operator==(const Circuit&, const Circuit&); std::vector bincodeSerialize() const; @@ -1383,7 +1266,8 @@ namespace Program { namespace Program { inline bool operator==(const AssertionPayload &lhs, const AssertionPayload &rhs) { - if (!(lhs.value == rhs.value)) { return false; } + if (!(lhs.error_selector == rhs.error_selector)) { return false; } + if (!(lhs.payload == rhs.payload)) { return false; } return true; } @@ -1408,7 +1292,8 @@ template <> template void serde::Serializable::serialize(const Program::AssertionPayload &obj, Serializer &serializer) { serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); + serde::Serializable::serialize(obj.error_selector, serializer); + serde::Serializable::serialize(obj.payload, serializer); serializer.decrease_container_depth(); } @@ -1417,87 +1302,12 @@ template Program::AssertionPayload serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); Program::AssertionPayload obj; - obj.value = serde::Deserializable::deserialize(deserializer); + obj.error_selector = serde::Deserializable::deserialize(deserializer); + obj.payload = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { - - inline bool operator==(const AssertionPayload::StaticString &lhs, const AssertionPayload::StaticString &rhs) { - if (!(lhs.value == rhs.value)) { return false; } - return true; - } - - inline std::vector AssertionPayload::StaticString::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline AssertionPayload::StaticString AssertionPayload::StaticString::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::AssertionPayload::StaticString &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); -} - -template <> -template -Program::AssertionPayload::StaticString serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::AssertionPayload::StaticString obj; - obj.value = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - - inline bool operator==(const AssertionPayload::Dynamic &lhs, const AssertionPayload::Dynamic &rhs) { - if (!(lhs.value == rhs.value)) { return false; } - return true; - } - - inline std::vector AssertionPayload::Dynamic::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline AssertionPayload::Dynamic AssertionPayload::Dynamic::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::AssertionPayload::Dynamic &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); -} - -template <> -template -Program::AssertionPayload::Dynamic serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::AssertionPayload::Dynamic obj; - obj.value = serde::Deserializable::deserialize(deserializer); - return obj; -} - namespace Program { inline bool operator==(const BinaryFieldOp &lhs, const BinaryFieldOp &rhs) { @@ -2694,144 +2504,6 @@ Program::BlackBoxFuncCall::Blake3 serde::Deserializable BlackBoxFuncCall::SchnorrVerify::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxFuncCall::SchnorrVerify BlackBoxFuncCall::SchnorrVerify::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SchnorrVerify &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.public_key_x, serializer); - serde::Serializable::serialize(obj.public_key_y, serializer); - serde::Serializable::serialize(obj.signature, serializer); - serde::Serializable::serialize(obj.message, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Program::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::SchnorrVerify obj; - obj.public_key_x = serde::Deserializable::deserialize(deserializer); - obj.public_key_y = serde::Deserializable::deserialize(deserializer); - obj.signature = serde::Deserializable::deserialize(deserializer); - obj.message = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - - inline bool operator==(const BlackBoxFuncCall::PedersenCommitment &lhs, const BlackBoxFuncCall::PedersenCommitment &rhs) { - if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.domain_separator == rhs.domain_separator)) { return false; } - if (!(lhs.outputs == rhs.outputs)) { return false; } - return true; - } - - inline std::vector BlackBoxFuncCall::PedersenCommitment::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxFuncCall::PedersenCommitment BlackBoxFuncCall::PedersenCommitment::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::PedersenCommitment &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.domain_separator, serializer); - serde::Serializable::serialize(obj.outputs, serializer); -} - -template <> -template -Program::BlackBoxFuncCall::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::PedersenCommitment obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.domain_separator = serde::Deserializable::deserialize(deserializer); - obj.outputs = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - - inline bool operator==(const BlackBoxFuncCall::PedersenHash &lhs, const BlackBoxFuncCall::PedersenHash &rhs) { - if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.domain_separator == rhs.domain_separator)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } - return true; - } - - inline std::vector BlackBoxFuncCall::PedersenHash::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxFuncCall::PedersenHash BlackBoxFuncCall::PedersenHash::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::PedersenHash &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.domain_separator, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Program::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::PedersenHash obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.domain_separator = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - namespace Program { inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256k1 &lhs, const BlackBoxFuncCall::EcdsaSecp256k1 &rhs) { @@ -3020,50 +2692,6 @@ Program::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable BlackBoxFuncCall::Keccak256::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxFuncCall::Keccak256 BlackBoxFuncCall::Keccak256::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccak256 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.var_message_size, serializer); - serde::Serializable::serialize(obj.outputs, serializer); -} - -template <> -template -Program::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::Keccak256 obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.var_message_size = serde::Deserializable::deserialize(deserializer); - obj.outputs = serde::Deserializable::deserialize(deserializer); - return obj; -} - namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccakf1600 &lhs, const BlackBoxFuncCall::Keccakf1600 &rhs) { @@ -3675,208 +3303,23 @@ Program::BlackBoxOp::Blake3 serde::Deserializable:: return obj; } -namespace Program { - - inline bool operator==(const BlackBoxOp::Keccak256 &lhs, const BlackBoxOp::Keccak256 &rhs) { - if (!(lhs.message == rhs.message)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } - return true; - } - - inline std::vector BlackBoxOp::Keccak256::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxOp::Keccak256 BlackBoxOp::Keccak256::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::BlackBoxOp::Keccak256 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.message, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Program::BlackBoxOp::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::Keccak256 obj; - obj.message = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - namespace Program { inline bool operator==(const BlackBoxOp::Keccakf1600 &lhs, const BlackBoxOp::Keccakf1600 &rhs) { - if (!(lhs.message == rhs.message)) { return false; } + if (!(lhs.input == rhs.input)) { return false; } if (!(lhs.output == rhs.output)) { return false; } return true; } - inline std::vector BlackBoxOp::Keccakf1600::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::BlackBoxOp::Keccakf1600 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.message, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Program::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::Keccakf1600 obj; - obj.message = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - - inline bool operator==(const BlackBoxOp::EcdsaSecp256k1 &lhs, const BlackBoxOp::EcdsaSecp256k1 &rhs) { - if (!(lhs.hashed_msg == rhs.hashed_msg)) { return false; } - if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } - if (!(lhs.public_key_y == rhs.public_key_y)) { return false; } - if (!(lhs.signature == rhs.signature)) { return false; } - if (!(lhs.result == rhs.result)) { return false; } - return true; - } - - inline std::vector BlackBoxOp::EcdsaSecp256k1::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxOp::EcdsaSecp256k1 BlackBoxOp::EcdsaSecp256k1::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256k1 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.hashed_msg, serializer); - serde::Serializable::serialize(obj.public_key_x, serializer); - serde::Serializable::serialize(obj.public_key_y, serializer); - serde::Serializable::serialize(obj.signature, serializer); - serde::Serializable::serialize(obj.result, serializer); -} - -template <> -template -Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::EcdsaSecp256k1 obj; - obj.hashed_msg = serde::Deserializable::deserialize(deserializer); - obj.public_key_x = serde::Deserializable::deserialize(deserializer); - obj.public_key_y = serde::Deserializable::deserialize(deserializer); - obj.signature = serde::Deserializable::deserialize(deserializer); - obj.result = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - - inline bool operator==(const BlackBoxOp::EcdsaSecp256r1 &lhs, const BlackBoxOp::EcdsaSecp256r1 &rhs) { - if (!(lhs.hashed_msg == rhs.hashed_msg)) { return false; } - if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } - if (!(lhs.public_key_y == rhs.public_key_y)) { return false; } - if (!(lhs.signature == rhs.signature)) { return false; } - if (!(lhs.result == rhs.result)) { return false; } - return true; - } - - inline std::vector BlackBoxOp::EcdsaSecp256r1::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline BlackBoxOp::EcdsaSecp256r1 BlackBoxOp::EcdsaSecp256r1::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256r1 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.hashed_msg, serializer); - serde::Serializable::serialize(obj.public_key_x, serializer); - serde::Serializable::serialize(obj.public_key_y, serializer); - serde::Serializable::serialize(obj.signature, serializer); - serde::Serializable::serialize(obj.result, serializer); -} - -template <> -template -Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::EcdsaSecp256r1 obj; - obj.hashed_msg = serde::Deserializable::deserialize(deserializer); - obj.public_key_x = serde::Deserializable::deserialize(deserializer); - obj.public_key_y = serde::Deserializable::deserialize(deserializer); - obj.signature = serde::Deserializable::deserialize(deserializer); - obj.result = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - - inline bool operator==(const BlackBoxOp::SchnorrVerify &lhs, const BlackBoxOp::SchnorrVerify &rhs) { - if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } - if (!(lhs.public_key_y == rhs.public_key_y)) { return false; } - if (!(lhs.message == rhs.message)) { return false; } - if (!(lhs.signature == rhs.signature)) { return false; } - if (!(lhs.result == rhs.result)) { return false; } - return true; - } - - inline std::vector BlackBoxOp::SchnorrVerify::bincodeSerialize() const { + inline std::vector BlackBoxOp::Keccakf1600::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline BlackBoxOp::SchnorrVerify BlackBoxOp::SchnorrVerify::bincodeDeserialize(std::vector input) { + inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } @@ -3887,44 +3330,40 @@ namespace Program { template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::SchnorrVerify &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.public_key_x, serializer); - serde::Serializable::serialize(obj.public_key_y, serializer); - serde::Serializable::serialize(obj.message, serializer); - serde::Serializable::serialize(obj.signature, serializer); - serde::Serializable::serialize(obj.result, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::Keccakf1600 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.input, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::SchnorrVerify obj; - obj.public_key_x = serde::Deserializable::deserialize(deserializer); - obj.public_key_y = serde::Deserializable::deserialize(deserializer); - obj.message = serde::Deserializable::deserialize(deserializer); - obj.signature = serde::Deserializable::deserialize(deserializer); - obj.result = serde::Deserializable::deserialize(deserializer); +Program::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Keccakf1600 obj; + obj.input = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); return obj; } namespace Program { - inline bool operator==(const BlackBoxOp::PedersenCommitment &lhs, const BlackBoxOp::PedersenCommitment &rhs) { - if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.domain_separator == rhs.domain_separator)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } + inline bool operator==(const BlackBoxOp::EcdsaSecp256k1 &lhs, const BlackBoxOp::EcdsaSecp256k1 &rhs) { + if (!(lhs.hashed_msg == rhs.hashed_msg)) { return false; } + if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } + if (!(lhs.public_key_y == rhs.public_key_y)) { return false; } + if (!(lhs.signature == rhs.signature)) { return false; } + if (!(lhs.result == rhs.result)) { return false; } return true; } - inline std::vector BlackBoxOp::PedersenCommitment::bincodeSerialize() const { + inline std::vector BlackBoxOp::EcdsaSecp256k1::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline BlackBoxOp::PedersenCommitment BlackBoxOp::PedersenCommitment::bincodeDeserialize(std::vector input) { + inline BlackBoxOp::EcdsaSecp256k1 BlackBoxOp::EcdsaSecp256k1::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } @@ -3935,40 +3374,46 @@ namespace Program { template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenCommitment &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.domain_separator, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256k1 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.hashed_msg, serializer); + serde::Serializable::serialize(obj.public_key_x, serializer); + serde::Serializable::serialize(obj.public_key_y, serializer); + serde::Serializable::serialize(obj.signature, serializer); + serde::Serializable::serialize(obj.result, serializer); } template <> template -Program::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::PedersenCommitment obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.domain_separator = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); +Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::EcdsaSecp256k1 obj; + obj.hashed_msg = serde::Deserializable::deserialize(deserializer); + obj.public_key_x = serde::Deserializable::deserialize(deserializer); + obj.public_key_y = serde::Deserializable::deserialize(deserializer); + obj.signature = serde::Deserializable::deserialize(deserializer); + obj.result = serde::Deserializable::deserialize(deserializer); return obj; } namespace Program { - inline bool operator==(const BlackBoxOp::PedersenHash &lhs, const BlackBoxOp::PedersenHash &rhs) { - if (!(lhs.inputs == rhs.inputs)) { return false; } - if (!(lhs.domain_separator == rhs.domain_separator)) { return false; } - if (!(lhs.output == rhs.output)) { return false; } + inline bool operator==(const BlackBoxOp::EcdsaSecp256r1 &lhs, const BlackBoxOp::EcdsaSecp256r1 &rhs) { + if (!(lhs.hashed_msg == rhs.hashed_msg)) { return false; } + if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } + if (!(lhs.public_key_y == rhs.public_key_y)) { return false; } + if (!(lhs.signature == rhs.signature)) { return false; } + if (!(lhs.result == rhs.result)) { return false; } return true; } - inline std::vector BlackBoxOp::PedersenHash::bincodeSerialize() const { + inline std::vector BlackBoxOp::EcdsaSecp256r1::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline BlackBoxOp::PedersenHash BlackBoxOp::PedersenHash::bincodeDeserialize(std::vector input) { + inline BlackBoxOp::EcdsaSecp256r1 BlackBoxOp::EcdsaSecp256r1::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } @@ -3979,19 +3424,23 @@ namespace Program { template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenHash &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.domain_separator, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256r1 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.hashed_msg, serializer); + serde::Serializable::serialize(obj.public_key_x, serializer); + serde::Serializable::serialize(obj.public_key_y, serializer); + serde::Serializable::serialize(obj.signature, serializer); + serde::Serializable::serialize(obj.result, serializer); } template <> template -Program::BlackBoxOp::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::PedersenHash obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.domain_separator = serde::Deserializable::deserialize(deserializer); - obj.output = serde::Deserializable::deserialize(deserializer); +Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::EcdsaSecp256r1 obj; + obj.hashed_msg = serde::Deserializable::deserialize(deserializer); + obj.public_key_x = serde::Deserializable::deserialize(deserializer); + obj.public_key_y = serde::Deserializable::deserialize(deserializer); + obj.signature = serde::Deserializable::deserialize(deserializer); + obj.result = serde::Deserializable::deserialize(deserializer); return obj; } @@ -5732,8 +5181,7 @@ Program::BrilligOpcode::Trap serde::Deserializable namespace Program { inline bool operator==(const BrilligOpcode::Stop &lhs, const BrilligOpcode::Stop &rhs) { - if (!(lhs.return_data_offset == rhs.return_data_offset)) { return false; } - if (!(lhs.return_data_size == rhs.return_data_size)) { return false; } + if (!(lhs.return_data == rhs.return_data)) { return false; } return true; } @@ -5757,16 +5205,14 @@ namespace Program { template <> template void serde::Serializable::serialize(const Program::BrilligOpcode::Stop &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.return_data_offset, serializer); - serde::Serializable::serialize(obj.return_data_size, serializer); + serde::Serializable::serialize(obj.return_data, serializer); } template <> template Program::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { Program::BrilligOpcode::Stop obj; - obj.return_data_offset = serde::Deserializable::deserialize(deserializer); - obj.return_data_size = serde::Deserializable::deserialize(deserializer); + obj.return_data = serde::Deserializable::deserialize(deserializer); return obj; } @@ -5898,7 +5344,6 @@ namespace Program { if (!(lhs.public_parameters == rhs.public_parameters)) { return false; } if (!(lhs.return_values == rhs.return_values)) { return false; } if (!(lhs.assert_messages == rhs.assert_messages)) { return false; } - if (!(lhs.recursive == rhs.recursive)) { return false; } return true; } @@ -5930,7 +5375,6 @@ void serde::Serializable::serialize(const Program::Circuit &ob serde::Serializable::serialize(obj.public_parameters, serializer); serde::Serializable::serialize(obj.return_values, serializer); serde::Serializable::serialize(obj.assert_messages, serializer); - serde::Serializable::serialize(obj.recursive, serializer); serializer.decrease_container_depth(); } @@ -5946,7 +5390,6 @@ Program::Circuit serde::Deserializable::deserialize(Deserializ obj.public_parameters = serde::Deserializable::deserialize(deserializer); obj.return_values = serde::Deserializable::deserialize(deserializer); obj.assert_messages = serde::Deserializable::deserialize(deserializer); - obj.recursive = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } @@ -6069,92 +5512,6 @@ Program::ConstantOrWitnessEnum::Witness serde::Deserializable Directive::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline Directive Directive::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::Directive &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -Program::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Directive obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - -namespace Program { - - inline bool operator==(const Directive::ToLeRadix &lhs, const Directive::ToLeRadix &rhs) { - if (!(lhs.a == rhs.a)) { return false; } - if (!(lhs.b == rhs.b)) { return false; } - if (!(lhs.radix == rhs.radix)) { return false; } - return true; - } - - inline std::vector Directive::ToLeRadix::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline Directive::ToLeRadix Directive::ToLeRadix::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::Directive::ToLeRadix &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.a, serializer); - serde::Serializable::serialize(obj.b, serializer); - serde::Serializable::serialize(obj.radix, serializer); -} - -template <> -template -Program::Directive::ToLeRadix serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Directive::ToLeRadix obj; - obj.a = serde::Deserializable::deserialize(deserializer); - obj.b = serde::Deserializable::deserialize(deserializer); - obj.radix = serde::Deserializable::deserialize(deserializer); - return obj; -} - namespace Program { inline bool operator==(const Expression &lhs, const Expression &rhs) { @@ -6772,41 +6129,6 @@ Program::IntegerBitSize serde::Deserializable::deserial return obj; } -namespace Program { - - inline bool operator==(const IntegerBitSize::U0 &lhs, const IntegerBitSize::U0 &rhs) { - return true; - } - - inline std::vector IntegerBitSize::U0::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline IntegerBitSize::U0 IntegerBitSize::U0::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::IntegerBitSize::U0 &obj, Serializer &serializer) { -} - -template <> -template -Program::IntegerBitSize::U0 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::IntegerBitSize::U0 obj; - return obj; -} - namespace Program { inline bool operator==(const IntegerBitSize::U1 &lhs, const IntegerBitSize::U1 &rhs) { @@ -7109,20 +6431,20 @@ Program::MemoryAddress serde::Deserializable::deserializ namespace Program { - inline bool operator==(const Opcode &lhs, const Opcode &rhs) { + inline bool operator==(const MemoryAddress::Direct &lhs, const MemoryAddress::Direct &rhs) { if (!(lhs.value == rhs.value)) { return false; } return true; } - inline std::vector Opcode::bincodeSerialize() const { + inline std::vector MemoryAddress::Direct::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline Opcode Opcode::bincodeDeserialize(std::vector input) { + inline MemoryAddress::Direct MemoryAddress::Direct::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } @@ -7133,38 +6455,34 @@ namespace Program { template <> template -void serde::Serializable::serialize(const Program::Opcode &obj, Serializer &serializer) { - serializer.increase_container_depth(); +void serde::Serializable::serialize(const Program::MemoryAddress::Direct &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); } template <> template -Program::Opcode serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Opcode obj; +Program::MemoryAddress::Direct serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::MemoryAddress::Direct obj; obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); return obj; } namespace Program { - inline bool operator==(const Opcode::AssertZero &lhs, const Opcode::AssertZero &rhs) { + inline bool operator==(const MemoryAddress::Relative &lhs, const MemoryAddress::Relative &rhs) { if (!(lhs.value == rhs.value)) { return false; } return true; } - inline std::vector Opcode::AssertZero::bincodeSerialize() const { + inline std::vector MemoryAddress::Relative::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline Opcode::AssertZero Opcode::AssertZero::bincodeDeserialize(std::vector input) { + inline MemoryAddress::Relative MemoryAddress::Relative::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } @@ -7175,34 +6493,34 @@ namespace Program { template <> template -void serde::Serializable::serialize(const Program::Opcode::AssertZero &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::MemoryAddress::Relative &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::AssertZero obj; +Program::MemoryAddress::Relative serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::MemoryAddress::Relative obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } namespace Program { - inline bool operator==(const Opcode::BlackBoxFuncCall &lhs, const Opcode::BlackBoxFuncCall &rhs) { + inline bool operator==(const Opcode &lhs, const Opcode &rhs) { if (!(lhs.value == rhs.value)) { return false; } return true; } - inline std::vector Opcode::BlackBoxFuncCall::bincodeSerialize() const { + inline std::vector Opcode::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline Opcode::BlackBoxFuncCall Opcode::BlackBoxFuncCall::bincodeDeserialize(std::vector input) { + inline Opcode Opcode::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } @@ -7213,34 +6531,76 @@ namespace Program { template <> template -void serde::Serializable::serialize(const Program::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode &obj, Serializer &serializer) { + serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::BlackBoxFuncCall obj; +Program::Opcode serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::Opcode obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { + + inline bool operator==(const Opcode::AssertZero &lhs, const Opcode::AssertZero &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector Opcode::AssertZero::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline Opcode::AssertZero Opcode::AssertZero::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::Opcode::AssertZero &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); +} + +template <> +template +Program::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::AssertZero obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } namespace Program { - inline bool operator==(const Opcode::Directive &lhs, const Opcode::Directive &rhs) { + inline bool operator==(const Opcode::BlackBoxFuncCall &lhs, const Opcode::BlackBoxFuncCall &rhs) { if (!(lhs.value == rhs.value)) { return false; } return true; } - inline std::vector Opcode::Directive::bincodeSerialize() const { + inline std::vector Opcode::BlackBoxFuncCall::bincodeSerialize() const { auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); + serde::Serializable::serialize(*this, serializer); return std::move(serializer).bytes(); } - inline Opcode::Directive Opcode::Directive::bincodeDeserialize(std::vector input) { + inline Opcode::BlackBoxFuncCall Opcode::BlackBoxFuncCall::bincodeDeserialize(std::vector input) { auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); + auto value = serde::Deserializable::deserialize(deserializer); if (deserializer.get_buffer_offset() < input.size()) { throw serde::deserialization_error("Some input bytes were not read"); } @@ -7251,14 +6611,14 @@ namespace Program { template <> template -void serde::Serializable::serialize(const Program::Opcode::Directive &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::Opcode::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::Directive obj; +Program::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index 5c07a61af7e..700589d2040 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -4,12 +4,10 @@ //! implemented in more basic constraints. use serde::{Deserialize, Serialize}; -#[cfg(test)] use strum_macros::EnumIter; #[allow(clippy::upper_case_acronyms)] -#[derive(Clone, Debug, Hash, Copy, PartialEq, Eq, Serialize, Deserialize)] -#[cfg_attr(test, derive(EnumIter))] +#[derive(Clone, Debug, Hash, Copy, PartialEq, Eq, Serialize, Deserialize, EnumIter)] pub enum BlackBoxFunc { /// Ciphers (encrypts) the provided plaintext using AES128 in CBC mode, /// padding the input using PKCS#7. @@ -53,33 +51,6 @@ pub enum BlackBoxFunc { /// (witness, 8), constrained to be the blake3 of the inputs. Blake3, - /// Verify a Schnorr signature over the embedded curve - /// - inputs are: - /// - Public key as 2 (witness, 254) - /// - signature as a vector of 64 bytes (witness, 8) - /// - message as a vector of (witness, 8) - /// - output: A witness representing the result of the signature - /// verification; 0 for failure and 1 for success. - /// - /// Since the scalar field of the embedded curve is NOT the ACIR field, the - /// `(r,s)` signature is represented as a 64 bytes array for the two field - /// elements. On the other hand, the public key coordinates are ACIR fields. - /// The proving system decides how the message is to be hashed. Barretenberg - /// uses Blake2s. - /// - /// Verifies a Schnorr signature over a curve which is "pairing friendly" - /// with the curve on which the ACIR circuit is defined. - /// - /// The exact curve which this signature uses will vary based on the curve - /// being used by ACIR. For example, the BN254 curve supports Schnorr - /// signatures over the [Grumpkin][grumpkin] curve. - /// - /// [grumpkin]: https://hackmd.io/@aztec-network/ByzgNxBfd#2-Grumpkin---A-curve-on-top-of-BN-254-for-SNARK-efficient-group-operations - SchnorrVerify, - /// Will be deprecated - PedersenCommitment, - /// Will be deprecated - PedersenHash, /// Verifies a ECDSA signature over the secp256k1 curve. /// - inputs: /// - x coordinate of public key as 32 bytes @@ -87,11 +58,6 @@ pub enum BlackBoxFunc { /// - the signature, as a 64 bytes array /// - the hash of the message, as a vector of bytes /// - output: 0 for failure and 1 for success - /// - /// Inputs and outputs are similar to SchnorrVerify, except that because we - /// use a different curve (secp256k1), the field elements involved in the - /// signature and the public key are defined as an array of 32 bytes. - /// Another difference is that we assume the message is already hashed. EcdsaSecp256k1, /// Verifies a ECDSA signature over the secp256r1 curve. @@ -117,11 +83,6 @@ pub enum BlackBoxFunc { /// scalar $a$: `a=low+high*2^{128}`, with `low, high < 2^{128}` MultiScalarMul, - /// Computes the Keccak-256 (Ethereum version) of the inputs. - /// - inputs: Vector of bytes (witness, 8) - /// - outputs: Array of 32 bytes (witness, 8) - Keccak256, - /// Keccak Permutation function of width 1600 /// - inputs: An array of 25 64-bit Keccak lanes that represent a keccak sponge of 1600 bits /// - outputs: The result of a keccak f1600 permutation on the input state. Also an array of 25 Keccak lanes. @@ -207,7 +168,6 @@ impl BlackBoxFunc { pub fn name(&self) -> &'static str { match self { BlackBoxFunc::AES128Encrypt => "aes128_encrypt", - BlackBoxFunc::SchnorrVerify => "schnorr_verify", BlackBoxFunc::Blake2s => "blake2s", BlackBoxFunc::Blake3 => "blake3", BlackBoxFunc::EcdsaSecp256k1 => "ecdsa_secp256k1", @@ -216,7 +176,6 @@ impl BlackBoxFunc { BlackBoxFunc::AND => "and", BlackBoxFunc::XOR => "xor", BlackBoxFunc::RANGE => "range", - BlackBoxFunc::Keccak256 => "keccak256", BlackBoxFunc::Keccakf1600 => "keccakf1600", BlackBoxFunc::RecursiveAggregation => "recursive_aggregation", BlackBoxFunc::EcdsaSecp256r1 => "ecdsa_secp256r1", @@ -228,15 +187,12 @@ impl BlackBoxFunc { BlackBoxFunc::BigIntToLeBytes => "bigint_to_le_bytes", BlackBoxFunc::Poseidon2Permutation => "poseidon2_permutation", BlackBoxFunc::Sha256Compression => "sha256_compression", - BlackBoxFunc::PedersenCommitment => "pedersen_commitment", - BlackBoxFunc::PedersenHash => "pedersen_hash", } } pub fn lookup(op_name: &str) -> Option { match op_name { "aes128_encrypt" => Some(BlackBoxFunc::AES128Encrypt), - "schnorr_verify" => Some(BlackBoxFunc::SchnorrVerify), "blake2s" => Some(BlackBoxFunc::Blake2s), "blake3" => Some(BlackBoxFunc::Blake3), "ecdsa_secp256k1" => Some(BlackBoxFunc::EcdsaSecp256k1), @@ -246,7 +202,6 @@ impl BlackBoxFunc { "and" => Some(BlackBoxFunc::AND), "xor" => Some(BlackBoxFunc::XOR), "range" => Some(BlackBoxFunc::RANGE), - "keccak256" => Some(BlackBoxFunc::Keccak256), "keccakf1600" => Some(BlackBoxFunc::Keccakf1600), "recursive_aggregation" => Some(BlackBoxFunc::RecursiveAggregation), "bigint_add" => Some(BlackBoxFunc::BigIntAdd), @@ -257,8 +212,6 @@ impl BlackBoxFunc { "bigint_to_le_bytes" => Some(BlackBoxFunc::BigIntToLeBytes), "poseidon2_permutation" => Some(BlackBoxFunc::Poseidon2Permutation), "sha256_compression" => Some(BlackBoxFunc::Sha256Compression), - "pedersen_commitment" => Some(BlackBoxFunc::PedersenCommitment), - "pedersen_hash" => Some(BlackBoxFunc::PedersenHash), _ => None, } } diff --git a/acvm-repo/acir/src/circuit/brillig.rs b/acvm-repo/acir/src/circuit/brillig.rs index a9714ce29b2..ef75d088f8c 100644 --- a/acvm-repo/acir/src/circuit/brillig.rs +++ b/acvm-repo/acir/src/circuit/brillig.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; /// Inputs for the Brillig VM. These are the initial inputs /// that the Brillig VM will use to start. -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug, Hash)] pub enum BrilligInputs { Single(Expression), Array(Vec>), @@ -14,7 +14,7 @@ pub enum BrilligInputs { /// Outputs for the Brillig VM. Once the VM has completed /// execution, this will be the object that is returned. -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug, Hash)] pub enum BrilligOutputs { Simple(Witness), Array(Vec), @@ -23,7 +23,7 @@ pub enum BrilligOutputs { /// This is purely a wrapper struct around a list of Brillig opcode's which represents /// a full Brillig function to be executed by the Brillig VM. /// This is stored separately on a program and accessed through a [BrilligPointer]. -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default, Debug)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default, Debug, Hash)] pub struct BrilligBytecode { pub bytecode: Vec>, } diff --git a/acvm-repo/acir/src/circuit/directives.rs b/acvm-repo/acir/src/circuit/directives.rs deleted file mode 100644 index 3bc66288590..00000000000 --- a/acvm-repo/acir/src/circuit/directives.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::native_types::{Expression, Witness}; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -/// Directives do not apply any constraints. -/// You can think of them as opcodes that allow one to use non-determinism -/// In the future, this can be replaced with asm non-determinism blocks -pub enum Directive { - //decomposition of a: a=\sum b[i]*radix^i where b is an array of witnesses < radix in little endian form - ToLeRadix { a: Expression, b: Vec, radix: u32 }, -} diff --git a/acvm-repo/acir/src/circuit/mod.rs b/acvm-repo/acir/src/circuit/mod.rs index f700fefe0cd..4ff581bf17a 100644 --- a/acvm-repo/acir/src/circuit/mod.rs +++ b/acvm-repo/acir/src/circuit/mod.rs @@ -1,6 +1,5 @@ pub mod black_box_functions; pub mod brillig; -pub mod directives; pub mod opcodes; use crate::native_types::{Expression, Witness}; @@ -26,7 +25,7 @@ use self::{brillig::BrilligBytecode, opcodes::BlockId}; /// Bounded Expressions are useful if you are eventually going to pass the ACIR /// into a proving system which supports PLONK, where arithmetic expressions have a /// finite fan-in. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default, Hash)] pub enum ExpressionWidth { #[default] Unbounded, @@ -37,13 +36,13 @@ pub enum ExpressionWidth { /// A program represented by multiple ACIR circuits. The execution trace of these /// circuits is dictated by construction of the [crate::native_types::WitnessStack]. -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default, Hash)] pub struct Program { pub functions: Vec>, pub unconstrained_functions: Vec>, } -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default, Hash)] pub struct Circuit { // current_witness_index is the highest witness index in the circuit. The next witness to be added to this circuit // will take on this value. (The value is cached here as an optimization.) @@ -68,23 +67,18 @@ pub struct Circuit { // c++ code at the moment when it is, due to OpcodeLocation needing a comparison // implementation which is never generated. pub assert_messages: Vec<(OpcodeLocation, AssertionPayload)>, - - /// States whether the backend should use a SNARK recursion friendly prover. - /// If implemented by a backend, this means that proofs generated with this circuit - /// will be friendly for recursively verifying inside of another SNARK. - pub recursive: bool, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] pub enum ExpressionOrMemory { Expression(Expression), Memory(BlockId), } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum AssertionPayload { - StaticString(String), - Dynamic(/* error_selector */ u64, Vec>), +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] +pub struct AssertionPayload { + pub error_selector: u64, + pub payload: Vec>, } #[derive(Debug, Copy, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)] @@ -120,12 +114,6 @@ impl<'de> Deserialize<'de> for ErrorSelector { } } -/// This selector indicates that the payload is a string. -/// This is used to parse any error with a string payload directly, -/// to avoid users having to parse the error externally to the ACVM. -/// Only non-string errors need to be parsed externally to the ACVM using the circuit ABI. -pub const STRING_ERROR_SELECTOR: ErrorSelector = ErrorSelector(0); - #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] pub struct RawAssertionPayload { pub selector: ErrorSelector, @@ -367,7 +355,7 @@ impl std::fmt::Debug for Program { } } -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default, Hash)] pub struct PublicInputs(pub BTreeSet); impl PublicInputs { @@ -418,34 +406,16 @@ mod tests { Opcode::BlackBoxFuncCall(BlackBoxFuncCall::Keccakf1600 { inputs, outputs }) } - fn schnorr_verify_opcode() -> Opcode { - let public_key_x = FunctionInput::witness(Witness(1), FieldElement::max_num_bits()); - let public_key_y = FunctionInput::witness(Witness(2), FieldElement::max_num_bits()); - let signature: Box<[FunctionInput; 64]> = - Box::new(std::array::from_fn(|i| FunctionInput::witness(Witness(i as u32 + 3), 8))); - let message: Vec> = vec![FunctionInput::witness(Witness(67), 8)]; - let output = Witness(68); - - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::SchnorrVerify { - public_key_x, - public_key_y, - signature, - message, - output, - }) - } - #[test] fn serialization_roundtrip() { let circuit = Circuit { current_witness_index: 5, expression_width: ExpressionWidth::Unbounded, - opcodes: vec![and_opcode::(), range_opcode(), schnorr_verify_opcode()], + opcodes: vec![and_opcode::(), range_opcode()], private_parameters: BTreeSet::new(), public_parameters: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(12)])), return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(4), Witness(12)])), assert_messages: Default::default(), - recursive: false, }; let program = Program { functions: vec![circuit], unconstrained_functions: Vec::new() }; @@ -475,13 +445,11 @@ mod tests { range_opcode(), and_opcode(), keccakf1600_opcode(), - schnorr_verify_opcode(), ], private_parameters: BTreeSet::new(), public_parameters: PublicInputs(BTreeSet::from_iter(vec![Witness(2)])), return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2)])), assert_messages: Default::default(), - recursive: false, }; let program = Program { functions: vec![circuit], unconstrained_functions: Vec::new() }; diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index 848d7bda84b..f47c40b0dd7 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -1,7 +1,4 @@ -use super::{ - brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, - directives::Directive, -}; +use super::brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}; pub mod function_id; pub use function_id::AcirFunctionId; @@ -18,7 +15,7 @@ pub use black_box_function_call::{ }; pub use memory_operation::{BlockId, MemOp}; -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] pub enum BlockType { Memory, CallData(u32), @@ -32,7 +29,7 @@ impl BlockType { } #[allow(clippy::large_enum_variant)] -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] pub enum Opcode { /// An `AssertZero` opcode adds the constraint that `P(w) = 0`, where /// `w=(w_1,..w_n)` is a tuple of `n` witnesses, and `P` is a multi-variate @@ -60,7 +57,7 @@ pub enum Opcode { /// specialized constraints. /// /// Often used for exposing more efficient implementations of - /// SNARK-unfriendly computations. + /// SNARK-unfriendly computations. /// /// All black box functions take as input a tuple `(witness, num_bits)`, /// where `num_bits` is a constant representing the bit size of the input @@ -75,16 +72,6 @@ pub enum Opcode { /// embedded curve. BlackBoxFuncCall(BlackBoxFuncCall), - /// This opcode is a specialization of a Brillig opcode. Instead of having - /// some generic assembly code like Brillig, a directive has a hardcoded - /// name which tells the solver which computation to do: with Brillig, the - /// computation refers to the compiled bytecode of an unconstrained Noir - /// function, but with a directive, the computation is hardcoded inside the - /// compiler. - /// - /// Directives will be replaced by Brillig opcodes in the future. - Directive(Directive), - /// Atomic operation on a block of memory /// /// ACIR is able to address any array of witnesses. Each array is assigned @@ -158,18 +145,6 @@ impl std::fmt::Display for Opcode { } Opcode::BlackBoxFuncCall(g) => write!(f, "{g}"), - Opcode::Directive(Directive::ToLeRadix { a, b, radix: _ }) => { - write!(f, "DIR::TORADIX ")?; - write!( - f, - // TODO (Note): this assumes that the decomposed bits have contiguous witness indices - // This should be the case, however, we can also have a function which checks this - "(_{}, [_{}..._{}] )", - a, - b.first().unwrap().witness_index(), - b.last().unwrap().witness_index(), - ) - } Opcode::MemoryOp { block_id, op, predicate } => { write!(f, "MEM ")?; if let Some(pred) = predicate { diff --git a/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index fbe179d7c04..9cf31e94eb4 100644 --- a/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeSet; + use crate::native_types::Witness; use crate::{AcirField, BlackBoxFunc}; @@ -7,13 +9,13 @@ use thiserror::Error; // Note: Some functions will not use all of the witness // So we need to supply how many bits of the witness is needed -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] pub enum ConstantOrWitnessEnum { Constant(F), Witness(Witness), } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] pub struct FunctionInput { input: ConstantOrWitnessEnum, num_bits: u32, @@ -42,6 +44,10 @@ impl FunctionInput { pub fn witness(witness: Witness, num_bits: u32) -> FunctionInput { FunctionInput { input: ConstantOrWitnessEnum::Witness(witness), num_bits } } + + pub fn is_constant(&self) -> bool { + matches!(self.input, ConstantOrWitnessEnum::Constant(_)) + } } #[derive(Clone, PartialEq, Eq, Debug, Error)] @@ -73,7 +79,7 @@ impl std::fmt::Display for FunctionInput { } } -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] pub enum BlackBoxFuncCall { AES128Encrypt { inputs: Vec>, @@ -102,29 +108,6 @@ pub enum BlackBoxFuncCall { inputs: Vec>, outputs: Box<[Witness; 32]>, }, - SchnorrVerify { - public_key_x: FunctionInput, - public_key_y: FunctionInput, - #[serde( - serialize_with = "serialize_big_array", - deserialize_with = "deserialize_big_array_into_box" - )] - signature: Box<[FunctionInput; 64]>, - message: Vec>, - output: Witness, - }, - /// Will be deprecated - PedersenCommitment { - inputs: Vec>, - domain_separator: u32, - outputs: (Witness, Witness), - }, - /// Will be deprecated - PedersenHash { - inputs: Vec>, - domain_separator: u32, - output: Witness, - }, EcdsaSecp256k1 { public_key_x: Box<[FunctionInput; 32]>, public_key_y: Box<[FunctionInput; 32]>, @@ -157,15 +140,6 @@ pub enum BlackBoxFuncCall { input2: Box<[FunctionInput; 3]>, outputs: (Witness, Witness, Witness), }, - Keccak256 { - inputs: Vec>, - /// This is the number of bytes to take - /// from the input. Note: if `var_message_size` - /// is more than the number of bytes in the input, - /// then an error is returned. - var_message_size: FunctionInput, - outputs: Box<[Witness; 32]>, - }, Keccakf1600 { inputs: Box<[FunctionInput; 25]>, outputs: Box<[Witness; 25]>, @@ -249,12 +223,10 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::RANGE { .. } => BlackBoxFunc::RANGE, BlackBoxFuncCall::Blake2s { .. } => BlackBoxFunc::Blake2s, BlackBoxFuncCall::Blake3 { .. } => BlackBoxFunc::Blake3, - BlackBoxFuncCall::SchnorrVerify { .. } => BlackBoxFunc::SchnorrVerify, BlackBoxFuncCall::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1, BlackBoxFuncCall::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1, BlackBoxFuncCall::MultiScalarMul { .. } => BlackBoxFunc::MultiScalarMul, BlackBoxFuncCall::EmbeddedCurveAdd { .. } => BlackBoxFunc::EmbeddedCurveAdd, - BlackBoxFuncCall::Keccak256 { .. } => BlackBoxFunc::Keccak256, BlackBoxFuncCall::Keccakf1600 { .. } => BlackBoxFunc::Keccakf1600, BlackBoxFuncCall::RecursiveAggregation { .. } => BlackBoxFunc::RecursiveAggregation, BlackBoxFuncCall::BigIntAdd { .. } => BlackBoxFunc::BigIntAdd, @@ -265,8 +237,6 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::BigIntToLeBytes { .. } => BlackBoxFunc::BigIntToLeBytes, BlackBoxFuncCall::Poseidon2Permutation { .. } => BlackBoxFunc::Poseidon2Permutation, BlackBoxFuncCall::Sha256Compression { .. } => BlackBoxFunc::Sha256Compression, - BlackBoxFuncCall::PedersenCommitment { .. } => BlackBoxFunc::PedersenCommitment, - BlackBoxFuncCall::PedersenHash { .. } => BlackBoxFunc::PedersenHash, } } @@ -280,8 +250,6 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::Blake2s { inputs, .. } | BlackBoxFuncCall::Blake3 { inputs, .. } | BlackBoxFuncCall::BigIntFromLeBytes { inputs, .. } - | BlackBoxFuncCall::PedersenCommitment { inputs, .. } - | BlackBoxFuncCall::PedersenHash { inputs, .. } | BlackBoxFuncCall::Poseidon2Permutation { inputs, .. } => inputs.to_vec(), BlackBoxFuncCall::Keccakf1600 { inputs, .. } => inputs.to_vec(), @@ -308,21 +276,6 @@ impl BlackBoxFuncCall { vec![input1[0], input1[1], input2[0], input2[1]] } BlackBoxFuncCall::RANGE { input } => vec![*input], - BlackBoxFuncCall::SchnorrVerify { - public_key_x, - public_key_y, - signature, - message, - .. - } => { - let mut inputs: Vec> = - Vec::with_capacity(2 + signature.len() + message.len()); - inputs.push(*public_key_x); - inputs.push(*public_key_y); - inputs.extend(signature.iter().copied()); - inputs.extend(message.iter().copied()); - inputs - } BlackBoxFuncCall::EcdsaSecp256k1 { public_key_x, public_key_y, @@ -361,11 +314,6 @@ impl BlackBoxFuncCall { inputs.extend(hashed_message.iter().copied()); inputs } - BlackBoxFuncCall::Keccak256 { inputs, var_message_size, .. } => { - let mut inputs = inputs.clone(); - inputs.push(*var_message_size); - inputs - } BlackBoxFuncCall::RecursiveAggregation { verification_key: key, proof, @@ -386,8 +334,7 @@ impl BlackBoxFuncCall { pub fn get_outputs_vec(&self) -> Vec { match self { BlackBoxFuncCall::Blake2s { outputs, .. } - | BlackBoxFuncCall::Blake3 { outputs, .. } - | BlackBoxFuncCall::Keccak256 { outputs, .. } => outputs.to_vec(), + | BlackBoxFuncCall::Blake3 { outputs, .. } => outputs.to_vec(), BlackBoxFuncCall::Keccakf1600 { outputs, .. } => outputs.to_vec(), @@ -398,11 +345,8 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::AND { output, .. } | BlackBoxFuncCall::XOR { output, .. } - | BlackBoxFuncCall::SchnorrVerify { output, .. } | BlackBoxFuncCall::EcdsaSecp256k1 { output, .. } - | BlackBoxFuncCall::PedersenHash { output, .. } | BlackBoxFuncCall::EcdsaSecp256r1 { output, .. } => vec![*output], - BlackBoxFuncCall::PedersenCommitment { outputs, .. } => vec![outputs.0, outputs.1], BlackBoxFuncCall::MultiScalarMul { outputs, .. } | BlackBoxFuncCall::EmbeddedCurveAdd { outputs, .. } => { vec![outputs.0, outputs.1, outputs.2] @@ -419,6 +363,16 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::BigIntToLeBytes { outputs, .. } => outputs.to_vec(), } } + + pub fn get_input_witnesses(&self) -> BTreeSet { + let mut result = BTreeSet::new(); + for input in self.get_inputs_vec() { + if let ConstantOrWitnessEnum::Witness(w) = input.input() { + result.insert(w); + } + } + result + } } const ABBREVIATION_LIMIT: usize = 5; @@ -475,14 +429,6 @@ fn get_outputs_string(outputs: &[Witness]) -> String { impl std::fmt::Display for BlackBoxFuncCall { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - BlackBoxFuncCall::PedersenCommitment { .. } => { - return write!(f, "BLACKBOX::Deprecated") - } - BlackBoxFuncCall::PedersenHash { .. } => return write!(f, "BLACKBOX::Deprecated"), - _ => (), - } - let uppercase_name = self.name().to_uppercase(); write!(f, "BLACKBOX::{uppercase_name} ")?; // INPUTS @@ -551,22 +497,6 @@ mod tests { Opcode::BlackBoxFuncCall(BlackBoxFuncCall::Keccakf1600 { inputs, outputs }) } - fn schnorr_verify_opcode() -> Opcode { - let public_key_x = FunctionInput::witness(Witness(1), FieldElement::max_num_bits()); - let public_key_y = FunctionInput::witness(Witness(2), FieldElement::max_num_bits()); - let signature: Box<[FunctionInput; 64]> = - Box::new(std::array::from_fn(|i| FunctionInput::witness(Witness(i as u32 + 3), 8))); - let message: Vec> = vec![FunctionInput::witness(Witness(67), 8)]; - let output = Witness(68); - - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::SchnorrVerify { - public_key_x, - public_key_y, - signature, - message, - output, - }) - } #[test] fn keccakf1600_serialization_roundtrip() { @@ -575,12 +505,4 @@ mod tests { let recovered_opcode = bincode::deserialize(&buf).unwrap(); assert_eq!(opcode, recovered_opcode); } - - #[test] - fn schnorr_serialization_roundtrip() { - let opcode = schnorr_verify_opcode::(); - let buf = bincode::serialize(&opcode).unwrap(); - let recovered_opcode = bincode::deserialize(&buf).unwrap(); - assert_eq!(opcode, recovered_opcode); - } } diff --git a/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs b/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs index 90e3ee0563a..c9a78983204 100644 --- a/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs +++ b/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs @@ -7,7 +7,7 @@ pub struct BlockId(pub u32); /// Operation on a block of memory /// We can either write or read at an index in memory -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug, Hash)] pub struct MemOp { /// A constant expression that can be 0 (read) or 1 (write) pub operation: Expression, diff --git a/acvm-repo/acir/src/lib.rs b/acvm-repo/acir/src/lib.rs index 36331427b9f..bb5b50c0daf 100644 --- a/acvm-repo/acir/src/lib.rs +++ b/acvm-repo/acir/src/lib.rs @@ -35,14 +35,13 @@ mod reflection { use acir_field::FieldElement; use brillig::{ BinaryFieldOp, BinaryIntOp, BitSize, BlackBoxOp, HeapValueType, IntegerBitSize, - Opcode as BrilligOpcode, ValueOrArray, + MemoryAddress, Opcode as BrilligOpcode, ValueOrArray, }; use serde_reflection::{Tracer, TracerConfig}; use crate::{ circuit::{ brillig::{BrilligInputs, BrilligOutputs}, - directives::Directive, opcodes::{BlackBoxFuncCall, BlockType, ConstantOrWitnessEnum, FunctionInput}, AssertionPayload, Circuit, ExpressionOrMemory, ExpressionWidth, Opcode, OpcodeLocation, Program, @@ -77,13 +76,13 @@ mod reflection { tracer.trace_simple_type::>().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); - tracer.trace_simple_type::>().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::>().unwrap(); tracer.trace_simple_type::>().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); + tracer.trace_simple_type::().unwrap(); let registry = tracer.registry().unwrap(); diff --git a/acvm-repo/acir/tests/test_program_serialization.rs b/acvm-repo/acir/tests/test_program_serialization.rs index 6bf5afe52d9..305d94abcee 100644 --- a/acvm-repo/acir/tests/test_program_serialization.rs +++ b/acvm-repo/acir/tests/test_program_serialization.rs @@ -20,7 +20,9 @@ use acir::{ native_types::{Expression, Witness}, }; use acir_field::{AcirField, FieldElement}; -use brillig::{BitSize, HeapArray, HeapValueType, IntegerBitSize, MemoryAddress, ValueOrArray}; +use brillig::{ + BitSize, HeapArray, HeapValueType, HeapVector, IntegerBitSize, MemoryAddress, ValueOrArray, +}; #[test] fn addition_circuit() { @@ -47,11 +49,11 @@ fn addition_circuit() { let expected_serialization: Vec = vec![ 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 65, 14, 128, 32, 12, 4, 65, 124, 80, 75, 91, - 104, 111, 126, 69, 34, 252, 255, 9, 106, 228, 64, 162, 55, 153, 164, 217, 158, 38, 155, - 245, 238, 97, 189, 206, 187, 55, 161, 231, 214, 19, 254, 129, 126, 162, 107, 25, 92, 4, - 137, 185, 230, 88, 145, 112, 135, 104, 69, 5, 88, 74, 82, 84, 20, 149, 35, 42, 81, 85, 214, - 108, 197, 50, 24, 50, 85, 108, 98, 212, 186, 44, 204, 235, 5, 183, 99, 233, 46, 63, 252, - 110, 216, 56, 184, 15, 78, 146, 74, 173, 20, 141, 1, 0, 0, + 104, 111, 126, 69, 34, 252, 255, 9, 106, 228, 64, 194, 81, 38, 105, 182, 167, 201, 102, + 189, 251, 216, 159, 243, 110, 38, 244, 60, 122, 194, 63, 208, 47, 116, 109, 131, 139, 32, + 49, 215, 28, 43, 18, 158, 16, 173, 168, 0, 75, 73, 138, 138, 162, 114, 69, 37, 170, 202, + 154, 173, 88, 6, 67, 166, 138, 77, 140, 90, 151, 133, 117, 189, 224, 117, 108, 221, 229, + 135, 223, 13, 27, 135, 121, 106, 119, 3, 58, 173, 124, 163, 140, 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -91,67 +93,10 @@ fn multi_scalar_mul_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 141, 11, 10, 0, 32, 8, 67, 43, 181, 15, 221, 255, - 186, 145, 210, 130, 149, 240, 112, 234, 212, 156, 78, 12, 39, 67, 71, 158, 142, 80, 29, 44, - 228, 66, 90, 168, 119, 189, 74, 115, 131, 174, 78, 115, 58, 124, 70, 254, 130, 59, 74, 253, - 68, 255, 255, 221, 39, 54, 29, 134, 27, 102, 193, 0, 0, 0, - ]; - - assert_eq!(bytes, expected_serialization) -} - -#[test] -fn schnorr_verify_circuit() { - let public_key_x = FunctionInput::witness(Witness(1), FieldElement::max_num_bits()); - let public_key_y = FunctionInput::witness(Witness(2), FieldElement::max_num_bits()); - let signature: [FunctionInput; 64] = (3..(3 + 64)) - .map(|i| FunctionInput::witness(Witness(i), 8)) - .collect::>() - .try_into() - .unwrap(); - let message = - ((3 + 64)..(3 + 64 + 10)).map(|i| FunctionInput::witness(Witness(i), 8)).collect(); - let output = Witness(3 + 64 + 10); - let last_input = output.witness_index() - 1; - - let schnorr = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::SchnorrVerify { - public_key_x, - public_key_y, - signature: Box::new(signature), - message, - output, - }); - - let circuit: Circuit = Circuit { - current_witness_index: 100, - opcodes: vec![schnorr], - private_parameters: BTreeSet::from_iter((1..=last_input).map(Witness)), - return_values: PublicInputs(BTreeSet::from([output])), - ..Circuit::default() - }; - let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; - - let bytes = Program::serialize_program(&program); - - let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 85, 211, 103, 78, 2, 81, 24, 70, 225, 193, 130, 96, 239, - 189, 96, 239, 189, 35, 34, 34, 34, 34, 238, 130, 253, 47, 129, 192, 9, 223, 36, 7, 146, - 201, 60, 209, 31, 144, 123, 207, 155, 73, 250, 159, 118, 239, 201, 132, 121, 103, 227, 205, - 211, 137, 247, 144, 60, 220, 123, 114, 225, 17, 121, 84, 206, 202, 99, 114, 78, 206, 203, - 227, 242, 132, 60, 41, 79, 201, 211, 242, 140, 60, 43, 207, 201, 243, 242, 130, 188, 40, - 47, 201, 203, 242, 138, 188, 42, 175, 201, 235, 242, 134, 188, 41, 111, 201, 219, 242, 142, - 92, 144, 119, 229, 61, 121, 95, 62, 144, 15, 229, 35, 249, 88, 62, 145, 79, 229, 51, 249, - 92, 190, 144, 47, 229, 43, 249, 90, 190, 145, 111, 229, 59, 249, 94, 126, 144, 31, 229, 39, - 249, 89, 126, 145, 95, 229, 162, 252, 38, 151, 228, 119, 185, 44, 127, 200, 21, 249, 83, - 174, 134, 233, 52, 137, 191, 125, 233, 255, 53, 249, 91, 174, 203, 63, 114, 67, 254, 149, - 155, 242, 159, 220, 10, 255, 199, 247, 183, 244, 59, 216, 38, 155, 100, 139, 108, 144, 237, - 165, 155, 203, 199, 111, 102, 83, 108, 137, 13, 177, 29, 54, 195, 86, 216, 8, 219, 96, 19, - 108, 129, 13, 208, 62, 205, 211, 58, 141, 211, 54, 77, 211, 50, 13, 211, 46, 205, 22, 146, - 126, 163, 180, 73, 147, 180, 72, 131, 180, 71, 115, 180, 70, 99, 180, 69, 83, 180, 68, 67, - 180, 67, 51, 180, 66, 35, 180, 65, 19, 180, 64, 3, 220, 61, 119, 206, 93, 115, 199, 197, - 184, 211, 82, 220, 97, 57, 238, 172, 18, 119, 84, 141, 187, 168, 197, 217, 215, 227, 172, - 27, 113, 182, 205, 56, 203, 244, 204, 210, 115, 75, 116, 158, 3, 159, 46, 43, 32, 188, 53, - 25, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 77, 9, 10, 0, 48, 8, 114, 107, 231, 255, 255, 59, + 86, 204, 64, 22, 136, 102, 89, 5, 175, 182, 163, 80, 7, 47, 135, 73, 31, 56, 228, 42, 218, + 196, 203, 221, 38, 243, 78, 61, 28, 147, 119, 65, 31, 146, 53, 230, 210, 135, 252, 255, + 179, 90, 23, 212, 196, 199, 187, 192, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -162,31 +107,37 @@ fn simple_brillig_foreign_call() { let w_input = Witness(1); let w_inverted = Witness(2); + let value_address = MemoryAddress::direct(0); + let zero_usize = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ brillig::Opcode::Const { - destination: MemoryAddress(0), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(1_usize), + value: FieldElement::from(0_usize), }, brillig::Opcode::Const { - destination: MemoryAddress(1), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0_usize), + value: FieldElement::from(1_usize), }, brillig::Opcode::CalldataCopy { - destination_address: MemoryAddress(0), - size_address: MemoryAddress(0), - offset_address: MemoryAddress(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, brillig::Opcode::ForeignCall { function: "invert".into(), - destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], + destinations: vec![ValueOrArray::MemoryAddress(value_address)], destination_value_types: vec![HeapValueType::field()], - inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], + inputs: vec![ValueOrArray::MemoryAddress(value_address)], input_value_types: vec![HeapValueType::field()], }, - brillig::Opcode::Stop { return_data_offset: 0, return_data_size: 1 }, + brillig::Opcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: one_usize }, + }, ], }; @@ -214,12 +165,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, 81, 73, 10, 192, 48, 8, 140, 165, 91, 160, 183, - 126, 196, 254, 160, 159, 233, 161, 151, 30, 74, 200, 251, 19, 136, 130, 132, 196, 75, 28, - 16, 199, 17, 212, 65, 112, 5, 123, 14, 32, 190, 80, 230, 90, 130, 181, 155, 50, 142, 225, - 2, 187, 89, 40, 239, 157, 106, 2, 82, 116, 138, 51, 118, 239, 171, 222, 108, 232, 218, 139, - 125, 198, 179, 113, 83, 188, 29, 57, 86, 226, 239, 23, 159, 63, 104, 63, 238, 213, 45, 237, - 108, 244, 18, 195, 174, 252, 193, 92, 2, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 203, 10, 128, 48, 12, 179, 243, 57, 240, 230, + 143, 108, 127, 224, 207, 120, 240, 226, 65, 196, 239, 119, 98, 11, 101, 100, 94, 214, 64, + 73, 26, 88, 73, 24, 53, 31, 166, 52, 196, 186, 99, 150, 93, 67, 188, 149, 57, 212, 33, 146, + 221, 173, 160, 243, 186, 92, 144, 54, 127, 138, 245, 204, 62, 243, 95, 110, 13, 195, 122, + 144, 207, 240, 126, 28, 65, 71, 7, 250, 206, 105, 6, 214, 251, 113, 111, 231, 133, 190, 93, + 191, 40, 237, 37, 127, 1, 190, 36, 121, 0, 128, 254, 118, 42, 127, 2, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -242,55 +193,61 @@ fn complex_brillig_foreign_call() { let brillig_bytecode = BrilligBytecode { bytecode: vec![ brillig::Opcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(3_usize), }, brillig::Opcode::Const { - destination: MemoryAddress(1), + destination: MemoryAddress::direct(1), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0_usize), }, brillig::Opcode::CalldataCopy { - destination_address: MemoryAddress(32), - size_address: MemoryAddress(0), - offset_address: MemoryAddress(1), + destination_address: MemoryAddress::direct(32), + size_address: MemoryAddress::direct(0), + offset_address: MemoryAddress::direct(1), }, brillig::Opcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), value: FieldElement::from(32_usize), bit_size: BitSize::Integer(IntegerBitSize::U32), }, brillig::Opcode::Const { - destination: MemoryAddress(3), + destination: MemoryAddress::direct(3), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(1_usize), }, brillig::Opcode::Const { - destination: MemoryAddress(4), + destination: MemoryAddress::direct(4), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(3_usize), }, brillig::Opcode::CalldataCopy { - destination_address: MemoryAddress(1), - size_address: MemoryAddress(3), - offset_address: MemoryAddress(4), + destination_address: MemoryAddress::direct(1), + size_address: MemoryAddress::direct(3), + offset_address: MemoryAddress::direct(4), }, // Oracles are named 'foreign calls' in brillig brillig::Opcode::ForeignCall { function: "complex".into(), inputs: vec![ - ValueOrArray::HeapArray(HeapArray { pointer: 0.into(), size: 3 }), - ValueOrArray::MemoryAddress(MemoryAddress::from(1)), + ValueOrArray::HeapArray(HeapArray { + pointer: MemoryAddress::direct(0), + size: 3, + }), + ValueOrArray::MemoryAddress(MemoryAddress::direct(1)), ], input_value_types: vec![ HeapValueType::Array { size: 3, value_types: vec![HeapValueType::field()] }, HeapValueType::field(), ], destinations: vec![ - ValueOrArray::HeapArray(HeapArray { pointer: 0.into(), size: 3 }), - ValueOrArray::MemoryAddress(MemoryAddress::from(35)), - ValueOrArray::MemoryAddress(MemoryAddress::from(36)), + ValueOrArray::HeapArray(HeapArray { + pointer: MemoryAddress::direct(0), + size: 3, + }), + ValueOrArray::MemoryAddress(MemoryAddress::direct(35)), + ValueOrArray::MemoryAddress(MemoryAddress::direct(36)), ], destination_value_types: vec![ HeapValueType::Array { size: 3, value_types: vec![HeapValueType::field()] }, @@ -298,7 +255,22 @@ fn complex_brillig_foreign_call() { HeapValueType::field(), ], }, - brillig::Opcode::Stop { return_data_offset: 32, return_data_size: 5 }, + brillig::Opcode::Const { + destination: MemoryAddress::direct(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(32_usize), + }, + brillig::Opcode::Const { + destination: MemoryAddress::direct(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(5_usize), + }, + brillig::Opcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(1), + }, + }, ], }; @@ -338,17 +310,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, 85, 81, 14, 194, 48, 8, 133, 118, 186, 53, 241, - 207, 11, 152, 232, 1, 58, 189, 128, 119, 49, 254, 105, 244, 211, 227, 59, 50, 154, 49, 214, - 100, 31, 163, 201, 246, 146, 133, 174, 5, 10, 15, 72, 17, 122, 52, 221, 135, 188, 222, 177, - 116, 44, 105, 223, 195, 24, 73, 247, 206, 50, 46, 67, 139, 118, 190, 98, 169, 24, 221, 6, - 98, 244, 5, 98, 4, 81, 255, 21, 214, 219, 178, 46, 166, 252, 249, 204, 252, 84, 208, 207, - 215, 158, 255, 107, 150, 141, 38, 154, 140, 28, 76, 7, 111, 132, 212, 61, 65, 201, 116, 86, - 217, 101, 115, 11, 226, 62, 99, 223, 145, 88, 56, 205, 228, 102, 127, 239, 53, 6, 69, 184, - 97, 78, 109, 96, 127, 37, 106, 81, 11, 126, 100, 103, 17, 14, 48, 116, 213, 227, 243, 254, - 190, 158, 63, 175, 40, 149, 102, 132, 179, 88, 95, 212, 57, 42, 59, 109, 43, 33, 31, 140, - 156, 46, 102, 244, 230, 124, 31, 97, 104, 141, 244, 48, 253, 1, 180, 46, 168, 159, 181, 6, - 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 205, 14, 130, 48, 12, 238, 54, 20, 136, 222, + 124, 1, 19, 125, 128, 161, 241, 238, 187, 24, 111, 26, 61, 250, 248, 178, 216, 198, 89, 26, + 56, 216, 18, 248, 146, 165, 12, 218, 175, 255, 193, 193, 7, 85, 123, 28, 62, 23, 40, 61, + 202, 244, 62, 192, 47, 72, 247, 140, 50, 254, 135, 198, 233, 113, 69, 171, 24, 253, 12, 98, + 12, 6, 49, 66, 214, 255, 9, 246, 91, 179, 47, 170, 245, 11, 194, 254, 164, 221, 90, 180, + 103, 137, 247, 18, 101, 197, 11, 157, 140, 60, 116, 23, 47, 7, 13, 207, 10, 101, 45, 124, + 87, 76, 232, 88, 51, 191, 202, 252, 145, 138, 177, 133, 254, 124, 109, 243, 60, 68, 226, + 15, 38, 252, 177, 33, 254, 194, 168, 79, 37, 171, 87, 158, 75, 238, 119, 13, 223, 1, 188, + 60, 238, 207, 219, 245, 21, 4, 83, 110, 158, 176, 99, 247, 189, 80, 178, 33, 14, 66, 254, + 159, 233, 211, 119, 130, 254, 144, 205, 88, 163, 98, 180, 18, 167, 13, 116, 65, 190, 222, + 250, 76, 4, 233, 188, 7, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -386,11 +358,11 @@ fn memory_op_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 82, 65, 10, 0, 32, 8, 211, 180, 255, 216, 15, 250, - 255, 171, 10, 82, 176, 232, 150, 30, 26, 200, 118, 144, 49, 135, 8, 11, 117, 14, 169, 102, - 229, 162, 140, 78, 219, 206, 137, 174, 44, 111, 104, 217, 190, 24, 236, 75, 113, 94, 146, - 93, 174, 252, 86, 46, 71, 223, 78, 46, 104, 129, 253, 155, 45, 60, 195, 5, 3, 89, 11, 161, - 73, 39, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 144, 75, 10, 0, 32, 8, 68, 253, 117, 31, 187, 65, + 247, 63, 85, 65, 10, 82, 203, 116, 209, 128, 60, 221, 12, 227, 32, 108, 181, 53, 108, 187, + 147, 140, 24, 118, 231, 169, 97, 212, 55, 245, 106, 95, 76, 246, 229, 60, 47, 173, 46, 87, + 127, 43, 87, 178, 127, 231, 16, 148, 194, 29, 195, 11, 220, 154, 119, 139, 115, 25, 38, 3, + 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -489,15 +461,15 @@ fn nested_acir_call_circuit() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 205, 146, 97, 10, 195, 32, 12, 133, 163, 66, 207, 147, - 24, 173, 241, 223, 174, 50, 153, 189, 255, 17, 214, 177, 148, 57, 17, 250, 99, 14, 250, - 224, 97, 144, 16, 146, 143, 231, 224, 45, 167, 126, 105, 217, 109, 118, 91, 248, 200, 168, - 225, 248, 63, 107, 114, 208, 233, 104, 188, 233, 139, 191, 137, 108, 51, 139, 113, 13, 161, - 38, 95, 137, 233, 142, 62, 23, 137, 24, 98, 89, 133, 132, 162, 196, 135, 23, 230, 42, 65, - 82, 46, 57, 97, 166, 192, 149, 182, 152, 121, 211, 97, 110, 222, 94, 8, 13, 132, 182, 54, - 48, 144, 235, 8, 254, 11, 22, 76, 132, 101, 231, 237, 229, 23, 189, 213, 54, 119, 15, 83, - 212, 199, 172, 175, 191, 226, 102, 96, 140, 251, 202, 84, 13, 204, 141, 224, 25, 176, 161, - 158, 53, 121, 144, 73, 14, 4, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 146, 81, 10, 195, 48, 8, 134, 77, 164, 247, 209, + 152, 52, 230, 109, 87, 89, 88, 122, 255, 35, 172, 99, 41, 11, 89, 161, 15, 77, 31, 250, + 193, 143, 34, 34, 250, 35, 194, 23, 172, 250, 48, 173, 50, 171, 44, 252, 48, 85, 176, 213, + 143, 154, 16, 58, 182, 198, 71, 141, 116, 14, 182, 205, 44, 161, 217, 251, 18, 93, 97, 225, + 39, 185, 148, 53, 144, 15, 121, 86, 86, 14, 26, 94, 78, 69, 138, 122, 141, 41, 167, 72, + 137, 189, 20, 94, 66, 146, 165, 14, 195, 113, 123, 17, 52, 38, 180, 185, 129, 127, 176, 51, + 240, 42, 175, 96, 160, 87, 118, 220, 94, 110, 170, 183, 218, 230, 238, 221, 39, 234, 191, + 172, 207, 177, 171, 153, 155, 153, 106, 96, 236, 3, 30, 249, 181, 199, 27, 99, 149, 130, + 253, 11, 4, 0, 0, ]; assert_eq!(bytes, expected_serialization); } diff --git a/acvm-repo/acir_field/Cargo.toml b/acvm-repo/acir_field/Cargo.toml index 168628b0d4a..039aefe355e 100644 --- a/acvm-repo/acir_field/Cargo.toml +++ b/acvm-repo/acir_field/Cargo.toml @@ -2,7 +2,7 @@ name = "acir_field" description = "The field implementation being used by ACIR." # x-release-please-start-version -version = "0.50.0" +version = "1.0.0-beta.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acir_field/src/field_element.rs b/acvm-repo/acir_field/src/field_element.rs index 2323f008dbe..0249b410aa7 100644 --- a/acvm-repo/acir_field/src/field_element.rs +++ b/acvm-repo/acir_field/src/field_element.rs @@ -8,8 +8,8 @@ use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign}; use crate::AcirField; // XXX: Switch out for a trait and proper implementations -// This implementation is in-efficient, can definitely remove hex usage and Iterator instances for trivial functionality -#[derive(Default, Clone, Copy, Eq, PartialOrd, Ord)] +// This implementation is inefficient, can definitely remove hex usage and Iterator instances for trivial functionality +#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct FieldElement(F); impl std::fmt::Display for FieldElement { @@ -33,46 +33,6 @@ impl std::fmt::Display for FieldElement { write!(f, "-")?; } - // Number of bits needed to represent the smaller representation - let num_bits = smaller_repr.bits(); - - // Check if the number represents a power of 2 - if smaller_repr.count_ones() == 1 { - let mut bit_index = 0; - for i in 0..num_bits { - if smaller_repr.bit(i) { - bit_index = i; - break; - } - } - return match bit_index { - 0 => write!(f, "1"), - 1 => write!(f, "2"), - 2 => write!(f, "4"), - 3 => write!(f, "8"), - _ => write!(f, "2{}", superscript(bit_index)), - }; - } - - // Check if number is a multiple of a power of 2. - // This is used because when computing the quotient - // we usually have numbers in the form 2^t * q + r - // We focus on 2^64, 2^32, 2^16, 2^8, 2^4 because - // they are common. We could extend this to a more - // general factorization strategy, but we pay in terms of CPU time - let mul_sign = "×"; - for power in [64, 32, 16, 8, 4] { - let power_of_two = BigUint::from(2_u128).pow(power); - if &smaller_repr % &power_of_two == BigUint::zero() { - return write!( - f, - "2{}{}{}", - superscript(power as u64), - mul_sign, - smaller_repr / &power_of_two, - ); - } - } write!(f, "{smaller_repr}") } } @@ -83,18 +43,6 @@ impl std::fmt::Debug for FieldElement { } } -impl std::hash::Hash for FieldElement { - fn hash(&self, state: &mut H) { - state.write(&self.to_be_bytes()); - } -} - -impl PartialEq for FieldElement { - fn eq(&self, other: &Self) -> bool { - self.to_be_bytes() == other.to_be_bytes() - } -} - impl From for FieldElement { fn from(mut a: i128) -> FieldElement { let mut negative = false; @@ -198,23 +146,6 @@ impl FieldElement { let fr = F::from_str(input).ok()?; Some(FieldElement(fr)) } - - fn bits(&self) -> Vec { - fn byte_to_bit(byte: u8) -> Vec { - let mut bits = Vec::with_capacity(8); - for index in (0..=7).rev() { - bits.push((byte & (1 << index)) >> index == 1); - } - bits - } - - let bytes = self.to_be_bytes(); - let mut bits = Vec::with_capacity(bytes.len() * 8); - for byte in bytes { - bits.extend(byte_to_bit(byte)); - } - bits - } } impl AcirField for FieldElement { @@ -264,12 +195,26 @@ impl AcirField for FieldElement { /// This is the number of bits required to represent this specific field element fn num_bits(&self) -> u32 { - let bits = self.bits(); - // Iterate the number of bits and pop off all leading zeroes - let iter = bits.iter().skip_while(|x| !(**x)); + let bytes = self.to_be_bytes(); + + // Iterate through the byte decomposition and pop off all leading zeroes + let mut iter = bytes.iter().skip_while(|x| (**x) == 0); + + // The first non-zero byte in the decomposition may have some leading zero-bits. + let Some(head_byte) = iter.next() else { + // If we don't have a non-zero byte then the field element is zero, + // which we consider to require a single bit to represent. + return 1; + }; + let num_bits_for_head_byte = head_byte.ilog2(); + + // Each remaining byte in the byte decomposition requires 8 bits. + // // Note: count will panic if it goes over usize::MAX. // This may not be suitable for devices whose usize < u16 - iter.count() as u32 + let tail_length = iter.count() as u32; + + 8 * tail_length + num_bits_for_head_byte + 1 } fn to_u128(self) -> u128 { @@ -409,40 +354,35 @@ impl SubAssign for FieldElement { } } -// For pretty printing powers -fn superscript(n: u64) -> String { - if n == 0 { - "⁰".to_owned() - } else if n == 1 { - "¹".to_owned() - } else if n == 2 { - "²".to_owned() - } else if n == 3 { - "³".to_owned() - } else if n == 4 { - "⁴".to_owned() - } else if n == 5 { - "⁵".to_owned() - } else if n == 6 { - "⁶".to_owned() - } else if n == 7 { - "⁷".to_owned() - } else if n == 8 { - "⁸".to_owned() - } else if n == 9 { - "⁹".to_owned() - } else if n >= 10 { - superscript(n / 10) + &superscript(n % 10) - } else { - panic!("{}", n.to_string() + " can't be converted to superscript."); - } -} - #[cfg(test)] mod tests { use super::{AcirField, FieldElement}; use proptest::prelude::*; + #[test] + fn requires_one_bit_to_hold_zero() { + let field = FieldElement::::zero(); + assert_eq!(field.num_bits(), 1); + } + + proptest! { + #[test] + fn num_bits_agrees_with_ilog2(num in 1u128..) { + let field = FieldElement::::from(num); + prop_assert_eq!(field.num_bits(), num.ilog2() + 1); + } + } + + #[test] + fn test_fits_in_u128() { + let field = FieldElement::::from(u128::MAX); + assert_eq!(field.num_bits(), 128); + assert!(field.fits_in_u128()); + let big_field = field + FieldElement::one(); + assert_eq!(big_field.num_bits(), 129); + assert!(!big_field.fits_in_u128()); + } + #[test] fn serialize_fixed_test_vectors() { // Serialized field elements from of 0, -1, -2, -3 diff --git a/acvm-repo/acvm/Cargo.toml b/acvm-repo/acvm/Cargo.toml index 29375a57a6e..ba01ac8ec16 100644 --- a/acvm-repo/acvm/Cargo.toml +++ b/acvm-repo/acvm/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm" description = "The virtual machine that processes ACIR given a backend/proof system." # x-release-please-start-version -version = "0.50.0" +version = "1.0.0-beta.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -14,11 +14,10 @@ repository.workspace = true workspace = true [dependencies] -num-bigint.workspace = true thiserror.workspace = true tracing.workspace = true serde.workspace = true - +fxhash.workspace = true acir.workspace = true brillig_vm.workspace = true acvm_blackbox_solver.workspace = true @@ -26,11 +25,7 @@ acvm_blackbox_solver.workspace = true indexmap = "1.7.0" [features] -bn254 = [ - "acir/bn254", - "brillig_vm/bn254", - "acvm_blackbox_solver/bn254", -] +bn254 = ["acir/bn254", "brillig_vm/bn254", "acvm_blackbox_solver/bn254"] bls12_381 = [ "acir/bls12_381", "brillig_vm/bls12_381", @@ -38,8 +33,11 @@ bls12_381 = [ ] [dev-dependencies] -ark-bls12-381 = { version = "^0.4.0", default-features = false, features = ["curve"] } +ark-bls12-381 = { version = "^0.4.0", default-features = false, features = [ + "curve", +] } ark-bn254.workspace = true bn254_blackbox_solver.workspace = true proptest.workspace = true zkhash = { version = "^0.2.0", default-features = false } +num-bigint.workspace = true diff --git a/acvm-repo/acvm/src/compiler/mod.rs b/acvm-repo/acvm/src/compiler/mod.rs index 5ece3d19a6e..daedd77c4a0 100644 --- a/acvm-repo/acvm/src/compiler/mod.rs +++ b/acvm-repo/acvm/src/compiler/mod.rs @@ -7,12 +7,18 @@ use acir::{ // The various passes that we can use over ACIR mod optimizers; +mod simulator; mod transformers; pub use optimizers::optimize; use optimizers::optimize_internal; -pub use transformers::transform; +pub use simulator::CircuitSimulator; use transformers::transform_internal; +pub use transformers::{transform, MIN_EXPRESSION_WIDTH}; + +/// We need multiple passes to stabilize the output. +/// The value was determined by running tests. +const MAX_OPTIMIZER_PASSES: usize = 3; /// This module moves and decomposes acir opcodes. The transformation map allows consumers of this module to map /// metadata they had about the opcodes to the new opcode structure generated after the transformation. @@ -26,9 +32,9 @@ impl AcirTransformationMap { /// Builds a map from a vector of pointers to the old acir opcodes. /// The index of the vector is the new opcode index. /// The value of the vector is the old opcode index pointed. - fn new(acir_opcode_positions: Vec) -> Self { + fn new(acir_opcode_positions: &[usize]) -> Self { let mut old_indices_to_new_indices = HashMap::with_capacity(acir_opcode_positions.len()); - for (new_index, old_index) in acir_opcode_positions.into_iter().enumerate() { + for (new_index, old_index) in acir_opcode_positions.iter().copied().enumerate() { old_indices_to_new_indices.entry(old_index).or_insert_with(Vec::new).push(new_index); } AcirTransformationMap { old_indices_to_new_indices } @@ -70,17 +76,51 @@ fn transform_assert_messages( } /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. +/// +/// Runs multiple passes until the output stabilizes. pub fn compile( acir: Circuit, expression_width: ExpressionWidth, ) -> (Circuit, AcirTransformationMap) { - let (acir, acir_opcode_positions) = optimize_internal(acir); + let acir_opcode_positions = (0..acir.opcodes.len()).collect::>(); + + if MAX_OPTIMIZER_PASSES == 0 { + return (acir, AcirTransformationMap::new(&acir_opcode_positions)); + } + + let mut pass = 0; + let mut prev_opcodes_hash = fxhash::hash64(&acir.opcodes); + let mut prev_acir = acir; + let mut prev_acir_opcode_positions = acir_opcode_positions; + + // For most test programs it would be enough to only loop `transform_internal`, + // but some of them don't stabilize unless we also repeat the backend agnostic optimizations. + let (mut acir, acir_opcode_positions) = loop { + let (acir, acir_opcode_positions) = + optimize_internal(prev_acir, prev_acir_opcode_positions); - let (mut acir, acir_opcode_positions) = - transform_internal(acir, expression_width, acir_opcode_positions); + // Stop if we have already done at least one transform and an extra optimization changed nothing. + if pass > 0 && prev_opcodes_hash == fxhash::hash64(&acir.opcodes) { + break (acir, acir_opcode_positions); + } + + let (acir, acir_opcode_positions) = + transform_internal(acir, expression_width, acir_opcode_positions); + + let opcodes_hash = fxhash::hash64(&acir.opcodes); + + // Stop if the output hasn't change in this loop or we went too long. + if pass == MAX_OPTIMIZER_PASSES - 1 || prev_opcodes_hash == opcodes_hash { + break (acir, acir_opcode_positions); + } - let transformation_map = AcirTransformationMap::new(acir_opcode_positions); + pass += 1; + prev_acir = acir; + prev_opcodes_hash = opcodes_hash; + prev_acir_opcode_positions = acir_opcode_positions; + }; + let transformation_map = AcirTransformationMap::new(&acir_opcode_positions); acir.assert_messages = transform_assert_messages(acir.assert_messages, &transformation_map); (acir, transformation_map) diff --git a/acvm-repo/acvm/src/compiler/optimizers/constant_backpropagation.rs b/acvm-repo/acvm/src/compiler/optimizers/constant_backpropagation.rs index 5b778f63f07..994cfc84e66 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/constant_backpropagation.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/constant_backpropagation.rs @@ -3,14 +3,13 @@ use std::collections::{BTreeMap, BTreeSet, HashMap}; use crate::{ compiler::optimizers::GeneralOptimizer, pwg::{ - arithmetic::ExpressionSolver, blackbox::solve_range_opcode, directives::solve_directives, - BrilligSolver, BrilligSolverStatus, + arithmetic::ExpressionSolver, blackbox::solve_range_opcode, BrilligSolver, + BrilligSolverStatus, }, }; use acir::{ circuit::{ brillig::{Brillig, BrilligInputs, BrilligOutputs}, - directives::Directive, opcodes::BlackBoxFuncCall, Circuit, Opcode, }, @@ -212,34 +211,6 @@ impl ConstantBackpropagationOptimizer { } } - Opcode::Directive(Directive::ToLeRadix { a, b, radix }) => { - if b.iter().all(|output| known_witnesses.contains_key(output)) { - continue; - } else if b.iter().any(|witness| required_witnesses.contains(witness)) { - // If one of the brillig opcode's outputs is a required witness then we can't remove the opcode. In this case we can't replace - // all of the uses of this witness with the calculated constant so we'll be attempting to use an uninitialized witness. - // - // We then do not attempt execution of this opcode and just simplify the inputs. - Opcode::Directive(Directive::ToLeRadix { - a: remap_expression(&known_witnesses, a), - b, - radix, - }) - } else { - let directive = Directive::ToLeRadix { - a: remap_expression(&known_witnesses, a), - b, - radix, - }; - let result = solve_directives(&mut known_witnesses, &directive); - - match result { - Ok(()) => continue, - Err(_) => Opcode::Directive(directive), - } - } - } - Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) => { if solve_range_opcode(&known_witnesses, &input).is_ok() { continue; @@ -288,7 +259,6 @@ mod tests { public_parameters: PublicInputs::default(), return_values: PublicInputs::default(), assert_messages: Default::default(), - recursive: false, } } diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs new file mode 100644 index 00000000000..43e32101cc5 --- /dev/null +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -0,0 +1,472 @@ +use std::collections::{BTreeMap, BTreeSet, HashMap}; + +use acir::{ + circuit::{ + brillig::{BrilligInputs, BrilligOutputs}, + opcodes::BlockId, + Circuit, Opcode, + }, + native_types::{Expression, Witness}, + AcirField, +}; + +use crate::compiler::CircuitSimulator; + +pub(crate) struct MergeExpressionsOptimizer { + resolved_blocks: HashMap>, + modified_gates: HashMap>, + deleted_gates: BTreeSet, +} + +impl MergeExpressionsOptimizer { + pub(crate) fn new() -> Self { + MergeExpressionsOptimizer { + resolved_blocks: HashMap::new(), + modified_gates: HashMap::new(), + deleted_gates: BTreeSet::new(), + } + } + /// This pass analyzes the circuit and identifies intermediate variables that are + /// only used in two gates. It then merges the gate that produces the + /// intermediate variable into the second one that uses it + /// Note: This pass is only relevant for backends that can handle unlimited width + pub(crate) fn eliminate_intermediate_variable( + &mut self, + circuit: &Circuit, + acir_opcode_positions: Vec, + ) -> (Vec>, Vec) { + // Initialization + self.modified_gates.clear(); + self.deleted_gates.clear(); + self.resolved_blocks.clear(); + + // Keep track, for each witness, of the gates that use it + let circuit_io: BTreeSet = + circuit.circuit_arguments().union(&circuit.public_inputs().0).cloned().collect(); + + let mut used_witness: BTreeMap> = BTreeMap::new(); + for (i, opcode) in circuit.opcodes.iter().enumerate() { + let witnesses = self.witness_inputs(opcode); + if let Opcode::MemoryInit { block_id, .. } = opcode { + self.resolved_blocks.insert(*block_id, witnesses.clone()); + } + for w in witnesses { + // We do not simplify circuit inputs and outputs + if !circuit_io.contains(&w) { + used_witness.entry(w).or_default().insert(i); + } + } + } + + // For each opcode, try to get a target opcode to merge with + for (i, opcode) in circuit.opcodes.iter().enumerate() { + if !matches!(opcode, Opcode::AssertZero(_)) { + continue; + } + if let Some(opcode) = self.get_opcode(i, circuit) { + let input_witnesses = self.witness_inputs(&opcode); + for w in input_witnesses { + let Some(gates_using_w) = used_witness.get(&w) else { + continue; + }; + // We only consider witness which are used in exactly two arithmetic gates + if gates_using_w.len() == 2 { + let first = *gates_using_w.first().expect("gates_using_w.len == 2"); + let second = *gates_using_w.last().expect("gates_using_w.len == 2"); + let b = if second == i { + first + } else { + // sanity check + assert!(i == first); + second + }; + // Merge the opcode with smaller index into the other one + // by updating modified_gates/deleted_gates/used_witness + // returns false if it could not merge them + let mut merge_opcodes = |op1, op2| -> bool { + if op1 == op2 { + return false; + } + let (source, target) = if op1 < op2 { (op1, op2) } else { (op2, op1) }; + let source_opcode = self.get_opcode(source, circuit); + let target_opcode = self.get_opcode(target, circuit); + if let ( + Some(Opcode::AssertZero(expr_use)), + Some(Opcode::AssertZero(expr_define)), + ) = (target_opcode, source_opcode) + { + if let Some(expr) = + Self::merge_expression(&expr_use, &expr_define, w) + { + self.modified_gates.insert(target, Opcode::AssertZero(expr)); + self.deleted_gates.insert(source); + // Update the 'used_witness' map to account for the merge. + let mut witness_list = CircuitSimulator::expr_wit(&expr_use); + witness_list.extend(CircuitSimulator::expr_wit(&expr_define)); + for w2 in witness_list { + if !circuit_io.contains(&w2) { + used_witness.entry(w2).and_modify(|v| { + v.insert(target); + v.remove(&source); + }); + } + } + return true; + } + } + false + }; + + if merge_opcodes(b, i) { + // We need to stop here and continue with the next opcode + // because the merge invalidates the current opcode. + break; + } + } + } + } + } + + // Construct the new circuit from modified/deleted gates + let mut new_circuit = Vec::new(); + let mut new_acir_opcode_positions = Vec::new(); + + for (i, opcode_position) in acir_opcode_positions.iter().enumerate() { + if let Some(op) = self.get_opcode(i, circuit) { + new_circuit.push(op); + new_acir_opcode_positions.push(*opcode_position); + } + } + (new_circuit, new_acir_opcode_positions) + } + + fn brillig_input_wit(&self, input: &BrilligInputs) -> BTreeSet { + let mut result = BTreeSet::new(); + match input { + BrilligInputs::Single(expr) => { + result.extend(CircuitSimulator::expr_wit(expr)); + } + BrilligInputs::Array(exprs) => { + for expr in exprs { + result.extend(CircuitSimulator::expr_wit(expr)); + } + } + BrilligInputs::MemoryArray(block_id) => { + let witnesses = self.resolved_blocks.get(block_id).expect("Unknown block id"); + result.extend(witnesses); + } + } + result + } + + fn brillig_output_wit(&self, output: &BrilligOutputs) -> BTreeSet { + let mut result = BTreeSet::new(); + match output { + BrilligOutputs::Simple(witness) => { + result.insert(*witness); + } + BrilligOutputs::Array(witnesses) => { + result.extend(witnesses); + } + } + result + } + + // Returns the input witnesses used by the opcode + fn witness_inputs(&self, opcode: &Opcode) -> BTreeSet { + match opcode { + Opcode::AssertZero(expr) => CircuitSimulator::expr_wit(expr), + Opcode::BlackBoxFuncCall(bb_func) => { + let mut witnesses = bb_func.get_input_witnesses(); + witnesses.extend(bb_func.get_outputs_vec()); + + witnesses + } + Opcode::MemoryOp { block_id: _, op, predicate } => { + //index et value, et predicate + let mut witnesses = CircuitSimulator::expr_wit(&op.index); + witnesses.extend(CircuitSimulator::expr_wit(&op.value)); + if let Some(p) = predicate { + witnesses.extend(CircuitSimulator::expr_wit(p)); + } + witnesses + } + + Opcode::MemoryInit { block_id: _, init, block_type: _ } => { + init.iter().cloned().collect() + } + Opcode::BrilligCall { inputs, outputs, .. } => { + let mut witnesses = BTreeSet::new(); + for i in inputs { + witnesses.extend(self.brillig_input_wit(i)); + } + for i in outputs { + witnesses.extend(self.brillig_output_wit(i)); + } + witnesses + } + Opcode::Call { id: _, inputs, outputs, predicate } => { + let mut witnesses: BTreeSet = BTreeSet::from_iter(inputs.iter().copied()); + witnesses.extend(outputs); + + if let Some(p) = predicate { + witnesses.extend(CircuitSimulator::expr_wit(p)); + } + witnesses + } + } + } + + // Merge 'expr' into 'target' via Gaussian elimination on 'w' + // Returns None if the expressions cannot be merged + fn merge_expression( + target: &Expression, + expr: &Expression, + w: Witness, + ) -> Option> { + // Check that the witness is not part of multiplication terms + for m in &target.mul_terms { + if m.1 == w || m.2 == w { + return None; + } + } + for m in &expr.mul_terms { + if m.1 == w || m.2 == w { + return None; + } + } + + for k in &target.linear_combinations { + if k.1 == w { + for i in &expr.linear_combinations { + if i.1 == w { + return Some(target.add_mul(-(k.0 / i.0), expr)); + } + } + } + } + None + } + + fn get_opcode(&self, g: usize, circuit: &Circuit) -> Option> { + if self.deleted_gates.contains(&g) { + return None; + } + self.modified_gates.get(&g).or(circuit.opcodes.get(g)).cloned() + } +} + +#[cfg(test)] +mod tests { + use crate::compiler::{optimizers::MergeExpressionsOptimizer, CircuitSimulator}; + use acir::{ + acir_field::AcirField, + circuit::{ + brillig::{BrilligFunctionId, BrilligOutputs}, + opcodes::{BlackBoxFuncCall, FunctionInput}, + Circuit, ExpressionWidth, Opcode, PublicInputs, + }, + native_types::{Expression, Witness}, + FieldElement, + }; + use std::collections::BTreeSet; + + fn check_circuit(circuit: Circuit) -> Circuit { + assert!(CircuitSimulator::default().check_circuit(&circuit)); + let mut merge_optimizer = MergeExpressionsOptimizer::new(); + let acir_opcode_positions = vec![0; 20]; + let (opcodes, _) = + merge_optimizer.eliminate_intermediate_variable(&circuit, acir_opcode_positions); + let mut optimized_circuit = circuit; + optimized_circuit.opcodes = opcodes; + // check that the circuit is still valid after optimization + assert!(CircuitSimulator::default().check_circuit(&optimized_circuit)); + optimized_circuit + } + + #[test] + fn does_not_eliminate_witnesses_returned_from_brillig() { + let opcodes = vec![ + Opcode::BrilligCall { + id: BrilligFunctionId::default(), + inputs: Vec::new(), + outputs: vec![BrilligOutputs::Simple(Witness(1))], + predicate: None, + }, + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::from(2_u128), Witness(0)), + (FieldElement::from(3_u128), Witness(1)), + (FieldElement::from(1_u128), Witness(2)), + ], + q_c: FieldElement::one(), + }), + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::from(2_u128), Witness(0)), + (FieldElement::from(2_u128), Witness(1)), + (FieldElement::from(1_u128), Witness(5)), + ], + q_c: FieldElement::one(), + }), + ]; + + let mut private_parameters = BTreeSet::new(); + private_parameters.insert(Witness(0)); + + let circuit = Circuit { + current_witness_index: 1, + expression_width: ExpressionWidth::Bounded { width: 4 }, + opcodes, + private_parameters, + public_parameters: PublicInputs::default(), + return_values: PublicInputs::default(), + assert_messages: Default::default(), + }; + check_circuit(circuit); + } + + #[test] + fn does_not_eliminate_witnesses_returned_from_circuit() { + let opcodes = vec![ + Opcode::AssertZero(Expression { + mul_terms: vec![(FieldElement::from(-1i128), Witness(0), Witness(0))], + linear_combinations: vec![(FieldElement::from(1i128), Witness(1))], + q_c: FieldElement::zero(), + }), + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::from(-1i128), Witness(1)), + (FieldElement::from(1i128), Witness(2)), + ], + q_c: FieldElement::zero(), + }), + ]; + // Witness(1) could be eliminated because it's only used by 2 opcodes. + + let mut private_parameters = BTreeSet::new(); + private_parameters.insert(Witness(0)); + + let mut return_values = BTreeSet::new(); + return_values.insert(Witness(1)); + return_values.insert(Witness(2)); + + let circuit = Circuit { + current_witness_index: 2, + expression_width: ExpressionWidth::Bounded { width: 4 }, + opcodes, + private_parameters, + public_parameters: PublicInputs::default(), + return_values: PublicInputs(return_values), + assert_messages: Default::default(), + }; + + let mut merge_optimizer = MergeExpressionsOptimizer::new(); + let acir_opcode_positions = vec![0; 20]; + let (opcodes, _) = + merge_optimizer.eliminate_intermediate_variable(&circuit, acir_opcode_positions); + + assert_eq!(opcodes.len(), 2); + } + + #[test] + fn does_not_attempt_to_merge_into_previous_opcodes() { + let opcodes = vec![ + Opcode::AssertZero(Expression { + mul_terms: vec![(FieldElement::one(), Witness(0), Witness(0))], + linear_combinations: vec![(-FieldElement::one(), Witness(4))], + q_c: FieldElement::zero(), + }), + Opcode::AssertZero(Expression { + mul_terms: vec![(FieldElement::one(), Witness(0), Witness(1))], + linear_combinations: vec![(FieldElement::one(), Witness(5))], + q_c: FieldElement::zero(), + }), + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (-FieldElement::one(), Witness(2)), + (FieldElement::one(), Witness(4)), + (FieldElement::one(), Witness(5)), + ], + q_c: FieldElement::zero(), + }), + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::one(), Witness(2)), + (-FieldElement::one(), Witness(3)), + (FieldElement::one(), Witness(4)), + (FieldElement::one(), Witness(5)), + ], + q_c: FieldElement::zero(), + }), + Opcode::BlackBoxFuncCall(acir::circuit::opcodes::BlackBoxFuncCall::RANGE { + input: FunctionInput::witness(Witness(3), 32), + }), + ]; + + let mut private_parameters = BTreeSet::new(); + private_parameters.insert(Witness(0)); + private_parameters.insert(Witness(1)); + let circuit = Circuit { + current_witness_index: 5, + expression_width: ExpressionWidth::Bounded { width: 4 }, + opcodes, + private_parameters, + public_parameters: PublicInputs::default(), + return_values: PublicInputs::default(), + assert_messages: Default::default(), + }; + check_circuit(circuit); + } + + #[test] + fn takes_blackbox_opcode_outputs_into_account() { + // Regression test for https://github.com/noir-lang/noir/issues/6527 + // Previously we would not track the usage of witness 4 in the output of the blackbox function. + // We would then merge the final two opcodes losing the check that the brillig call must match + // with `_0 ^ _1`. + + let circuit: Circuit = Circuit { + current_witness_index: 7, + opcodes: vec![ + Opcode::BrilligCall { + id: BrilligFunctionId(0), + inputs: Vec::new(), + outputs: vec![BrilligOutputs::Simple(Witness(3))], + predicate: None, + }, + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::AND { + lhs: FunctionInput::witness(Witness(0), 8), + rhs: FunctionInput::witness(Witness(1), 8), + output: Witness(4), + }), + Opcode::AssertZero(Expression { + linear_combinations: vec![ + (FieldElement::one(), Witness(3)), + (-FieldElement::one(), Witness(4)), + ], + ..Default::default() + }), + Opcode::AssertZero(Expression { + linear_combinations: vec![ + (-FieldElement::one(), Witness(2)), + (FieldElement::one(), Witness(4)), + ], + ..Default::default() + }), + ], + expression_width: ExpressionWidth::Bounded { width: 4 }, + private_parameters: BTreeSet::from([Witness(0), Witness(1)]), + return_values: PublicInputs(BTreeSet::from([Witness(2)])), + ..Default::default() + }; + + let new_circuit = check_circuit(circuit.clone()); + assert_eq!(circuit, new_circuit); + } +} diff --git a/acvm-repo/acvm/src/compiler/optimizers/mod.rs b/acvm-repo/acvm/src/compiler/optimizers/mod.rs index e20ad97a108..3531825c709 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/mod.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/mod.rs @@ -5,10 +5,12 @@ use acir::{ // mod constant_backpropagation; mod general; +mod merge_expressions; mod redundant_range; mod unused_memory; pub(crate) use general::GeneralOptimizer; +pub(crate) use merge_expressions::MergeExpressionsOptimizer; pub(crate) use redundant_range::RangeOptimizer; use tracing::info; @@ -19,9 +21,13 @@ use super::{transform_assert_messages, AcirTransformationMap}; /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] independent optimizations to a [`Circuit`]. pub fn optimize(acir: Circuit) -> (Circuit, AcirTransformationMap) { - let (mut acir, new_opcode_positions) = optimize_internal(acir); + // Track original acir opcode positions throughout the transformation passes of the compilation + // by applying the modifications done to the circuit opcodes and also to the opcode_positions (delete and insert) + let acir_opcode_positions = (0..acir.opcodes.len()).collect(); + + let (mut acir, new_opcode_positions) = optimize_internal(acir, acir_opcode_positions); - let transformation_map = AcirTransformationMap::new(new_opcode_positions); + let transformation_map = AcirTransformationMap::new(&new_opcode_positions); acir.assert_messages = transform_assert_messages(acir.assert_messages, &transformation_map); @@ -29,12 +35,13 @@ pub fn optimize(acir: Circuit) -> (Circuit, AcirTransformati } /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] independent optimizations to a [`Circuit`]. -#[tracing::instrument(level = "trace", name = "optimize_acir" skip(acir))] -pub(super) fn optimize_internal(acir: Circuit) -> (Circuit, Vec) { - // Track original acir opcode positions throughout the transformation passes of the compilation - // by applying the modifications done to the circuit opcodes and also to the opcode_positions (delete and insert) - let acir_opcode_positions = (0..acir.opcodes.len()).collect(); - +/// +/// Accepts an injected `acir_opcode_positions` to allow optimizations to be applied in a loop. +#[tracing::instrument(level = "trace", name = "optimize_acir" skip(acir, acir_opcode_positions))] +pub(super) fn optimize_internal( + acir: Circuit, + acir_opcode_positions: Vec, +) -> (Circuit, Vec) { if acir.opcodes.len() == 1 && matches!(acir.opcodes[0], Opcode::BrilligCall { .. }) { info!("Program is fully unconstrained, skipping optimization pass"); return (acir, acir_opcode_positions); diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index 3570a36a7e7..f9c715a277f 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -191,7 +191,6 @@ mod tests { public_parameters: PublicInputs::default(), return_values: PublicInputs::default(), assert_messages: Default::default(), - recursive: false, } } diff --git a/acvm-repo/acvm/src/compiler/simulator.rs b/acvm-repo/acvm/src/compiler/simulator.rs new file mode 100644 index 00000000000..893195f342a --- /dev/null +++ b/acvm-repo/acvm/src/compiler/simulator.rs @@ -0,0 +1,292 @@ +use acir::{ + circuit::{ + brillig::{BrilligInputs, BrilligOutputs}, + opcodes::{BlockId, FunctionInput}, + Circuit, Opcode, + }, + native_types::{Expression, Witness}, + AcirField, +}; +use std::collections::{BTreeSet, HashMap, HashSet}; + +#[derive(PartialEq)] +enum BlockStatus { + Initialized, + Used, +} + +/// Simulate a symbolic solve for a circuit +#[derive(Default)] +pub struct CircuitSimulator { + /// Track the witnesses that can be solved + solvable_witness: HashSet, + + /// Tells whether a Memory Block is: + /// - Not initialized if not in the map + /// - Initialized if its status is Initialized in the Map + /// - Used, indicating that the block cannot be written anymore. + resolved_blocks: HashMap, +} + +impl CircuitSimulator { + /// Simulate a symbolic solve for a circuit by keeping track of the witnesses that can be solved. + /// Returns false if the circuit cannot be solved + #[tracing::instrument(level = "trace", skip_all)] + pub fn check_circuit(&mut self, circuit: &Circuit) -> bool { + let circuit_inputs = circuit.circuit_arguments(); + self.solvable_witness.extend(circuit_inputs.iter()); + for op in &circuit.opcodes { + if !self.try_solve(op) { + return false; + } + } + true + } + + /// Check if the Opcode can be solved, and if yes, add the solved witness to set of solvable witness + fn try_solve(&mut self, opcode: &Opcode) -> bool { + let mut unresolved = HashSet::new(); + match opcode { + Opcode::AssertZero(expr) => { + for (_, w1, w2) in &expr.mul_terms { + if !self.solvable_witness.contains(w1) { + if !self.solvable_witness.contains(w2) { + return false; + } + unresolved.insert(*w1); + } + if !self.solvable_witness.contains(w2) && w1 != w2 { + unresolved.insert(*w2); + } + } + for (_, w) in &expr.linear_combinations { + if !self.solvable_witness.contains(w) { + unresolved.insert(*w); + } + } + if unresolved.len() == 1 { + self.mark_solvable(*unresolved.iter().next().unwrap()); + return true; + } + unresolved.is_empty() + } + Opcode::BlackBoxFuncCall(black_box_func_call) => { + let inputs = black_box_func_call.get_inputs_vec(); + for input in inputs { + if !self.can_solve_function_input(&input) { + return false; + } + } + let outputs = black_box_func_call.get_outputs_vec(); + for output in outputs { + self.mark_solvable(output); + } + true + } + Opcode::MemoryOp { block_id, op, predicate } => { + if !self.can_solve_expression(&op.index) { + return false; + } + if let Some(predicate) = predicate { + if !self.can_solve_expression(predicate) { + return false; + } + } + if op.operation.is_zero() { + let w = op.value.to_witness().unwrap(); + self.mark_solvable(w); + true + } else { + if let Some(BlockStatus::Used) = self.resolved_blocks.get(block_id) { + // Writing after having used the block should not be allowed + return false; + } + self.try_solve(&Opcode::AssertZero(op.value.clone())) + } + } + Opcode::MemoryInit { block_id, init, .. } => { + for w in init { + if !self.solvable_witness.contains(w) { + return false; + } + } + self.resolved_blocks.insert(*block_id, BlockStatus::Initialized); + true + } + Opcode::BrilligCall { id: _, inputs, outputs, predicate } => { + for input in inputs { + if !self.can_solve_brillig_input(input) { + return false; + } + } + if let Some(predicate) = predicate { + if !self.can_solve_expression(predicate) { + return false; + } + } + for output in outputs { + match output { + BrilligOutputs::Simple(w) => self.mark_solvable(*w), + BrilligOutputs::Array(arr) => { + for w in arr { + self.mark_solvable(*w); + } + } + } + } + true + } + Opcode::Call { id: _, inputs, outputs, predicate } => { + for w in inputs { + if !self.solvable_witness.contains(w) { + return false; + } + } + if let Some(predicate) = predicate { + if !self.can_solve_expression(predicate) { + return false; + } + } + for w in outputs { + self.mark_solvable(*w); + } + true + } + } + } + + /// Adds the witness to set of solvable witness + pub(crate) fn mark_solvable(&mut self, witness: Witness) { + self.solvable_witness.insert(witness); + } + + pub fn can_solve_function_input(&self, input: &FunctionInput) -> bool { + if !input.is_constant() { + return self.solvable_witness.contains(&input.to_witness()); + } + true + } + fn can_solve_expression(&self, expr: &Expression) -> bool { + for w in Self::expr_wit(expr) { + if !self.solvable_witness.contains(&w) { + return false; + } + } + true + } + fn can_solve_brillig_input(&mut self, input: &BrilligInputs) -> bool { + match input { + BrilligInputs::Single(expr) => self.can_solve_expression(expr), + BrilligInputs::Array(exprs) => { + for expr in exprs { + if !self.can_solve_expression(expr) { + return false; + } + } + true + } + + BrilligInputs::MemoryArray(block_id) => match self.resolved_blocks.entry(*block_id) { + std::collections::hash_map::Entry::Vacant(_) => false, + std::collections::hash_map::Entry::Occupied(entry) + if *entry.get() == BlockStatus::Used => + { + true + } + std::collections::hash_map::Entry::Occupied(mut entry) => { + entry.insert(BlockStatus::Used); + true + } + }, + } + } + + pub(crate) fn expr_wit(expr: &Expression) -> BTreeSet { + let mut result = BTreeSet::new(); + result.extend(expr.mul_terms.iter().flat_map(|i| vec![i.1, i.2])); + result.extend(expr.linear_combinations.iter().map(|i| i.1)); + result + } +} + +#[cfg(test)] +mod tests { + use std::collections::BTreeSet; + + use crate::compiler::CircuitSimulator; + use acir::{ + acir_field::AcirField, + circuit::{Circuit, ExpressionWidth, Opcode, PublicInputs}, + native_types::{Expression, Witness}, + FieldElement, + }; + + fn test_circuit( + opcodes: Vec>, + private_parameters: BTreeSet, + public_parameters: PublicInputs, + ) -> Circuit { + Circuit { + current_witness_index: 1, + expression_width: ExpressionWidth::Bounded { width: 4 }, + opcodes, + private_parameters, + public_parameters, + return_values: PublicInputs::default(), + assert_messages: Default::default(), + } + } + + #[test] + fn reports_true_for_empty_circuit() { + let empty_circuit = test_circuit(vec![], BTreeSet::default(), PublicInputs::default()); + + assert!(CircuitSimulator::default().check_circuit(&empty_circuit)); + } + + #[test] + fn reports_true_for_connected_circuit() { + let connected_circuit = test_circuit( + vec![Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::one(), Witness(1)), + (-FieldElement::one(), Witness(2)), + ], + q_c: FieldElement::zero(), + })], + BTreeSet::from([Witness(1)]), + PublicInputs::default(), + ); + + assert!(CircuitSimulator::default().check_circuit(&connected_circuit)); + } + + #[test] + fn reports_false_for_disconnected_circuit() { + let disconnected_circuit = test_circuit( + vec![ + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::one(), Witness(1)), + (-FieldElement::one(), Witness(2)), + ], + q_c: FieldElement::zero(), + }), + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::one(), Witness(3)), + (-FieldElement::one(), Witness(4)), + ], + q_c: FieldElement::zero(), + }), + ], + BTreeSet::from([Witness(1)]), + PublicInputs::default(), + ); + + assert!(!CircuitSimulator::default().check_circuit(&disconnected_circuit)); + } +} diff --git a/acvm-repo/acvm/src/compiler/transformers/csat.rs b/acvm-repo/acvm/src/compiler/transformers/csat.rs index f258e0a8818..bdd6998835a 100644 --- a/acvm-repo/acvm/src/compiler/transformers/csat.rs +++ b/acvm-repo/acvm/src/compiler/transformers/csat.rs @@ -6,6 +6,9 @@ use acir::{ }; use indexmap::IndexMap; +/// Minimum width accepted by the `CSatTransformer`. +pub const MIN_EXPRESSION_WIDTH: usize = 3; + /// A transformer which processes any [`Expression`]s to break them up such that they /// fit within the [`ProofSystemCompiler`][crate::ProofSystemCompiler]'s width. /// @@ -22,9 +25,11 @@ pub(crate) struct CSatTransformer { } impl CSatTransformer { - // Configure the width for the optimizer + /// Create an optimizer with a given width. + /// + /// Panics if `width` is less than `MIN_EXPRESSION_WIDTH`. pub(crate) fn new(width: usize) -> CSatTransformer { - assert!(width > 2); + assert!(width >= MIN_EXPRESSION_WIDTH, "width has to be at least {MIN_EXPRESSION_WIDTH}"); CSatTransformer { width, solvable_witness: HashSet::new() } } diff --git a/acvm-repo/acvm/src/compiler/transformers/mod.rs b/acvm-repo/acvm/src/compiler/transformers/mod.rs index 4fd8ba7883f..a499aec1b30 100644 --- a/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -1,5 +1,10 @@ use acir::{ - circuit::{brillig::BrilligOutputs, directives::Directive, Circuit, ExpressionWidth, Opcode}, + circuit::{ + self, + brillig::{BrilligInputs, BrilligOutputs}, + opcodes::{BlackBoxFuncCall, FunctionInput, MemOp}, + Circuit, ExpressionWidth, Opcode, + }, native_types::{Expression, Witness}, AcirField, }; @@ -8,8 +13,12 @@ use indexmap::IndexMap; mod csat; pub(crate) use csat::CSatTransformer; +pub use csat::MIN_EXPRESSION_WIDTH; -use super::{transform_assert_messages, AcirTransformationMap}; +use super::{ + optimizers::MergeExpressionsOptimizer, transform_assert_messages, AcirTransformationMap, + MAX_OPTIMIZER_PASSES, +}; /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. pub fn transform( @@ -23,7 +32,7 @@ pub fn transform( let (mut acir, acir_opcode_positions) = transform_internal(acir, expression_width, acir_opcode_positions); - let transformation_map = AcirTransformationMap::new(acir_opcode_positions); + let transformation_map = AcirTransformationMap::new(&acir_opcode_positions); acir.assert_messages = transform_assert_messages(acir.assert_messages, &transformation_map); @@ -33,9 +42,52 @@ pub fn transform( /// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. /// /// Accepts an injected `acir_opcode_positions` to allow transformations to be applied directly after optimizations. +/// +/// Does multiple passes until the output stabilizes. #[tracing::instrument(level = "trace", name = "transform_acir", skip(acir, acir_opcode_positions))] pub(super) fn transform_internal( - acir: Circuit, + mut acir: Circuit, + expression_width: ExpressionWidth, + mut acir_opcode_positions: Vec, +) -> (Circuit, Vec) { + // Allow multiple passes until we have stable output. + let mut prev_opcodes_hash = fxhash::hash64(&acir.opcodes); + + // For most test programs it would be enough to loop here, but some of them + // don't stabilize unless we also repeat the backend agnostic optimizations. + for _ in 0..MAX_OPTIMIZER_PASSES { + let (new_acir, new_acir_opcode_positions) = + transform_internal_once(acir, expression_width, acir_opcode_positions); + + acir = new_acir; + acir_opcode_positions = new_acir_opcode_positions; + + let new_opcodes_hash = fxhash::hash64(&acir.opcodes); + + if new_opcodes_hash == prev_opcodes_hash { + break; + } + prev_opcodes_hash = new_opcodes_hash; + } + // After the elimination of intermediate variables the `current_witness_index` is potentially higher than it needs to be, + // which would cause gaps if we ran the optimization a second time, making it look like new variables were added. + acir.current_witness_index = max_witness(&acir).witness_index(); + + (acir, acir_opcode_positions) +} + +/// Applies [`ProofSystemCompiler`][crate::ProofSystemCompiler] specific optimizations to a [`Circuit`]. +/// +/// Accepts an injected `acir_opcode_positions` to allow transformations to be applied directly after optimizations. +/// +/// Does a single optimization pass. +#[tracing::instrument( + level = "trace", + name = "transform_acir_once", + skip(acir, acir_opcode_positions) +)] +fn transform_internal_once( + mut acir: Circuit, expression_width: ExpressionWidth, acir_opcode_positions: Vec, ) -> (Circuit, Vec) { @@ -76,8 +128,6 @@ pub(super) fn transform_internal( &mut next_witness_index, ); - // Update next_witness counter - next_witness_index += (intermediate_variables.len() - len) as u32; let mut new_opcodes = Vec::new(); for (g, (norm, w)) in intermediate_variables.iter().skip(len) { // de-normalize @@ -101,17 +151,6 @@ pub(super) fn transform_internal( new_acir_opcode_positions.push(acir_opcode_positions[index]); transformed_opcodes.push(opcode); } - Opcode::Directive(ref directive) => { - match directive { - Directive::ToLeRadix { b, .. } => { - for witness in b { - transformer.mark_solvable(*witness); - } - } - } - new_acir_opcode_positions.push(acir_opcode_positions[index]); - transformed_opcodes.push(opcode); - } Opcode::MemoryInit { .. } => { // `MemoryInit` does not write values to the `WitnessMap` new_acir_opcode_positions.push(acir_opcode_positions[index]); @@ -158,7 +197,7 @@ pub(super) fn transform_internal( let current_witness_index = next_witness_index - 1; - let acir = Circuit { + acir = Circuit { current_witness_index, expression_width, opcodes: transformed_opcodes, @@ -166,5 +205,267 @@ pub(super) fn transform_internal( ..acir }; + let mut merge_optimizer = MergeExpressionsOptimizer::new(); + + let (opcodes, new_acir_opcode_positions) = + merge_optimizer.eliminate_intermediate_variable(&acir, new_acir_opcode_positions); + + // n.b. if we do not update current_witness_index after the eliminate_intermediate_variable pass, the real index could be less. + acir = Circuit { + opcodes, + // The optimizer does not add new public inputs + ..acir + }; + (acir, new_acir_opcode_positions) } + +/// Find the witness with the highest ID in the circuit. +fn max_witness(circuit: &Circuit) -> Witness { + let mut witnesses = WitnessFolder::new(Witness::default(), |state, witness| { + *state = witness.max(*state); + }); + witnesses.fold_circuit(circuit); + witnesses.into_state() +} + +/// Fold all witnesses in a circuit. +struct WitnessFolder { + state: S, + accumulate: A, +} + +impl WitnessFolder +where + A: Fn(&mut S, Witness), +{ + /// Create the folder with some initial state and an accumulator function. + fn new(init: S, accumulate: A) -> Self { + Self { state: init, accumulate } + } + + /// Take the accumulated state. + fn into_state(self) -> S { + self.state + } + + /// Add all witnesses from the circuit. + fn fold_circuit(&mut self, circuit: &Circuit) { + self.fold_many(circuit.private_parameters.iter()); + self.fold_many(circuit.public_parameters.0.iter()); + self.fold_many(circuit.return_values.0.iter()); + for opcode in &circuit.opcodes { + self.fold_opcode(opcode); + } + } + + /// Fold a witness into the state. + fn fold(&mut self, witness: Witness) { + (self.accumulate)(&mut self.state, witness); + } + + /// Fold many witnesses into the state. + fn fold_many<'w, I: Iterator>(&mut self, witnesses: I) { + for w in witnesses { + self.fold(*w); + } + } + + /// Add witnesses from the opcode. + fn fold_opcode(&mut self, opcode: &Opcode) { + match opcode { + Opcode::AssertZero(expr) => { + self.fold_expr(expr); + } + Opcode::BlackBoxFuncCall(call) => self.fold_blackbox(call), + Opcode::MemoryOp { block_id: _, op, predicate } => { + let MemOp { operation, index, value } = op; + self.fold_expr(operation); + self.fold_expr(index); + self.fold_expr(value); + if let Some(pred) = predicate { + self.fold_expr(pred); + } + } + Opcode::MemoryInit { block_id: _, init, block_type: _ } => { + for w in init { + self.fold(*w); + } + } + // We keep the display for a BrilligCall and circuit Call separate as they + // are distinct in their functionality and we should maintain this separation for debugging. + Opcode::BrilligCall { id: _, inputs, outputs, predicate } => { + if let Some(pred) = predicate { + self.fold_expr(pred); + } + self.fold_brillig_inputs(inputs); + self.fold_brillig_outputs(outputs); + } + Opcode::Call { id: _, inputs, outputs, predicate } => { + if let Some(pred) = predicate { + self.fold_expr(pred); + } + self.fold_many(inputs.iter()); + self.fold_many(outputs.iter()); + } + } + } + + fn fold_expr(&mut self, expr: &Expression) { + for i in &expr.mul_terms { + self.fold(i.1); + self.fold(i.2); + } + for i in &expr.linear_combinations { + self.fold(i.1); + } + } + + fn fold_brillig_inputs(&mut self, inputs: &[BrilligInputs]) { + for input in inputs { + match input { + BrilligInputs::Single(expr) => { + self.fold_expr(expr); + } + BrilligInputs::Array(exprs) => { + for expr in exprs { + self.fold_expr(expr); + } + } + BrilligInputs::MemoryArray(_) => {} + } + } + } + + fn fold_brillig_outputs(&mut self, outputs: &[BrilligOutputs]) { + for output in outputs { + match output { + BrilligOutputs::Simple(w) => { + self.fold(*w); + } + BrilligOutputs::Array(ws) => self.fold_many(ws.iter()), + } + } + } + + fn fold_blackbox(&mut self, call: &BlackBoxFuncCall) { + match call { + BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs } => { + self.fold_function_inputs(inputs.as_slice()); + self.fold_function_inputs(iv.as_slice()); + self.fold_function_inputs(key.as_slice()); + self.fold_many(outputs.iter()); + } + BlackBoxFuncCall::AND { lhs, rhs, output } => { + self.fold_function_input(lhs); + self.fold_function_input(rhs); + self.fold(*output); + } + BlackBoxFuncCall::XOR { lhs, rhs, output } => { + self.fold_function_input(lhs); + self.fold_function_input(rhs); + self.fold(*output); + } + BlackBoxFuncCall::RANGE { input } => { + self.fold_function_input(input); + } + BlackBoxFuncCall::Blake2s { inputs, outputs } => { + self.fold_function_inputs(inputs.as_slice()); + self.fold_many(outputs.iter()); + } + BlackBoxFuncCall::Blake3 { inputs, outputs } => { + self.fold_function_inputs(inputs.as_slice()); + self.fold_many(outputs.iter()); + } + BlackBoxFuncCall::EcdsaSecp256k1 { + public_key_x, + public_key_y, + signature, + hashed_message, + output, + } => { + self.fold_function_inputs(public_key_x.as_slice()); + self.fold_function_inputs(public_key_y.as_slice()); + self.fold_function_inputs(signature.as_slice()); + self.fold_function_inputs(hashed_message.as_slice()); + self.fold(*output); + } + BlackBoxFuncCall::EcdsaSecp256r1 { + public_key_x, + public_key_y, + signature, + hashed_message, + output, + } => { + self.fold_function_inputs(public_key_x.as_slice()); + self.fold_function_inputs(public_key_y.as_slice()); + self.fold_function_inputs(signature.as_slice()); + self.fold_function_inputs(hashed_message.as_slice()); + self.fold(*output); + } + BlackBoxFuncCall::MultiScalarMul { points, scalars, outputs } => { + self.fold_function_inputs(points.as_slice()); + self.fold_function_inputs(scalars.as_slice()); + let (x, y, i) = outputs; + self.fold(*x); + self.fold(*y); + self.fold(*i); + } + BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, outputs } => { + self.fold_function_inputs(input1.as_slice()); + self.fold_function_inputs(input2.as_slice()); + let (x, y, i) = outputs; + self.fold(*x); + self.fold(*y); + self.fold(*i); + } + BlackBoxFuncCall::Keccakf1600 { inputs, outputs } => { + self.fold_function_inputs(inputs.as_slice()); + self.fold_many(outputs.iter()); + } + BlackBoxFuncCall::RecursiveAggregation { + verification_key, + proof, + public_inputs, + key_hash, + proof_type: _, + } => { + self.fold_function_inputs(verification_key.as_slice()); + self.fold_function_inputs(proof.as_slice()); + self.fold_function_inputs(public_inputs.as_slice()); + self.fold_function_input(key_hash); + } + BlackBoxFuncCall::BigIntAdd { .. } + | BlackBoxFuncCall::BigIntSub { .. } + | BlackBoxFuncCall::BigIntMul { .. } + | BlackBoxFuncCall::BigIntDiv { .. } => {} + BlackBoxFuncCall::BigIntFromLeBytes { inputs, modulus: _, output: _ } => { + self.fold_function_inputs(inputs.as_slice()); + } + BlackBoxFuncCall::BigIntToLeBytes { input: _, outputs } => { + self.fold_many(outputs.iter()); + } + BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs, len: _ } => { + self.fold_function_inputs(inputs.as_slice()); + self.fold_many(outputs.iter()); + } + BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } => { + self.fold_function_inputs(inputs.as_slice()); + self.fold_function_inputs(hash_values.as_slice()); + self.fold_many(outputs.iter()); + } + } + } + + fn fold_function_input(&mut self, input: &FunctionInput) { + if let circuit::opcodes::ConstantOrWitnessEnum::Witness(witness) = input.input() { + self.fold(witness); + } + } + + fn fold_function_inputs(&mut self, inputs: &[FunctionInput]) { + for input in inputs { + self.fold_function_input(input); + } + } +} diff --git a/acvm-repo/acvm/src/pwg/blackbox/hash.rs b/acvm-repo/acvm/src/pwg/blackbox/hash.rs index f177cd071d0..7476b0dc2dc 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/hash.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/hash.rs @@ -49,7 +49,7 @@ fn get_hash_input( // in the message, then we error. if num_bytes_to_take > message_input.len() { return Err(OpcodeResolutionError::BlackBoxFunctionFailed( - acir::BlackBoxFunc::Keccak256, + acir::BlackBoxFunc::Blake2s, format!("the number of bytes to take from the message is more than the number of bytes in the message. {} > {}", num_bytes_to_take, message_input.len()), )); } diff --git a/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/acvm-repo/acvm/src/pwg/blackbox/mod.rs index 1cca14cc680..5137b18179b 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -3,7 +3,7 @@ use acir::{ native_types::{Witness, WitnessMap}, AcirField, }; -use acvm_blackbox_solver::{blake2s, blake3, keccak256, keccakf1600}; +use acvm_blackbox_solver::{blake2s, blake3, keccakf1600}; use self::{ aes128::solve_aes128_encryption_opcode, bigint::AcvmBigIntSolver, @@ -18,7 +18,6 @@ pub(crate) mod bigint; mod embedded_curve_ops; mod hash; mod logic; -mod pedersen; mod range; mod signature; pub(crate) mod utils; @@ -27,12 +26,8 @@ use embedded_curve_ops::{embedded_curve_add, multi_scalar_mul}; // Hash functions should eventually be exposed for external consumers. use hash::{solve_generic_256_hash_opcode, solve_sha_256_permutation_opcode}; use logic::{and, xor}; -use pedersen::{pedersen, pedersen_hash}; pub(crate) use range::solve_range_opcode; -use signature::{ - ecdsa::{secp256k1_prehashed, secp256r1_prehashed}, - schnorr::schnorr_verify, -}; +use signature::ecdsa::{secp256k1_prehashed, secp256r1_prehashed}; /// Check if all of the inputs to the function have assignments /// @@ -90,16 +85,6 @@ pub(crate) fn solve( BlackBoxFuncCall::Blake3 { inputs, outputs } => { solve_generic_256_hash_opcode(initial_witness, inputs, None, outputs, blake3) } - - BlackBoxFuncCall::Keccak256 { inputs, var_message_size, outputs } => { - solve_generic_256_hash_opcode( - initial_witness, - inputs, - Some(var_message_size), - outputs, - keccak256, - ) - } BlackBoxFuncCall::Keccakf1600 { inputs, outputs } => { let mut state = [0; 25]; for (it, input) in state.iter_mut().zip(inputs.as_ref()) { @@ -115,27 +100,6 @@ pub(crate) fn solve( } Ok(()) } - BlackBoxFuncCall::SchnorrVerify { - public_key_x, - public_key_y, - signature, - message, - output, - } => schnorr_verify( - backend, - initial_witness, - *public_key_x, - *public_key_y, - signature.as_ref(), - message, - *output, - ), - BlackBoxFuncCall::PedersenCommitment { inputs, domain_separator, outputs } => { - pedersen(backend, initial_witness, inputs, *domain_separator, *outputs) - } - BlackBoxFuncCall::PedersenHash { inputs, domain_separator, output } => { - pedersen_hash(backend, initial_witness, inputs, *domain_separator, *output) - } BlackBoxFuncCall::EcdsaSecp256k1 { public_key_x, public_key_y, diff --git a/acvm-repo/acvm/src/pwg/blackbox/pedersen.rs b/acvm-repo/acvm/src/pwg/blackbox/pedersen.rs deleted file mode 100644 index 654814bf92d..00000000000 --- a/acvm-repo/acvm/src/pwg/blackbox/pedersen.rs +++ /dev/null @@ -1,47 +0,0 @@ -use acir::{ - circuit::opcodes::FunctionInput, - native_types::{Witness, WitnessMap}, - AcirField, -}; - -use crate::{ - pwg::{input_to_value, insert_value, OpcodeResolutionError}, - BlackBoxFunctionSolver, -}; - -pub(super) fn pedersen( - backend: &impl BlackBoxFunctionSolver, - initial_witness: &mut WitnessMap, - inputs: &[FunctionInput], - domain_separator: u32, - outputs: (Witness, Witness), -) -> Result<(), OpcodeResolutionError> { - let scalars: Result, _> = - inputs.iter().map(|input| input_to_value(initial_witness, *input, false)).collect(); - let scalars: Vec<_> = scalars?.into_iter().collect(); - - let (res_x, res_y) = backend.pedersen_commitment(&scalars, domain_separator)?; - - insert_value(&outputs.0, res_x, initial_witness)?; - insert_value(&outputs.1, res_y, initial_witness)?; - - Ok(()) -} - -pub(super) fn pedersen_hash( - backend: &impl BlackBoxFunctionSolver, - initial_witness: &mut WitnessMap, - inputs: &[FunctionInput], - domain_separator: u32, - output: Witness, -) -> Result<(), OpcodeResolutionError> { - let scalars: Result, _> = - inputs.iter().map(|input| input_to_value(initial_witness, *input, false)).collect(); - let scalars: Vec<_> = scalars?.into_iter().collect(); - - let res = backend.pedersen_hash(&scalars, domain_separator)?; - - insert_value(&output, res, initial_witness)?; - - Ok(()) -} diff --git a/acvm-repo/acvm/src/pwg/blackbox/signature/mod.rs b/acvm-repo/acvm/src/pwg/blackbox/signature/mod.rs index 0cfb96740b8..b36ff499c6a 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/signature/mod.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/signature/mod.rs @@ -1,2 +1 @@ pub(super) mod ecdsa; -pub(super) mod schnorr; diff --git a/acvm-repo/acvm/src/pwg/blackbox/signature/schnorr.rs b/acvm-repo/acvm/src/pwg/blackbox/signature/schnorr.rs deleted file mode 100644 index a856303d065..00000000000 --- a/acvm-repo/acvm/src/pwg/blackbox/signature/schnorr.rs +++ /dev/null @@ -1,36 +0,0 @@ -use crate::{ - pwg::{ - blackbox::utils::{to_u8_array, to_u8_vec}, - input_to_value, insert_value, OpcodeResolutionError, - }, - BlackBoxFunctionSolver, -}; -use acir::{ - circuit::opcodes::FunctionInput, - native_types::{Witness, WitnessMap}, - AcirField, -}; - -#[allow(clippy::too_many_arguments)] -pub(crate) fn schnorr_verify( - backend: &impl BlackBoxFunctionSolver, - initial_witness: &mut WitnessMap, - public_key_x: FunctionInput, - public_key_y: FunctionInput, - signature: &[FunctionInput; 64], - message: &[FunctionInput], - output: Witness, -) -> Result<(), OpcodeResolutionError> { - let public_key_x: &F = &input_to_value(initial_witness, public_key_x, false)?; - let public_key_y: &F = &input_to_value(initial_witness, public_key_y, false)?; - - let signature = to_u8_array(initial_witness, signature)?; - let message = to_u8_vec(initial_witness, message)?; - - let valid_signature = - backend.schnorr_verify(public_key_x, public_key_y, &signature, &message)?; - - insert_value(&output, F::from(valid_signature), initial_witness)?; - - Ok(()) -} diff --git a/acvm-repo/acvm/src/pwg/brillig.rs b/acvm-repo/acvm/src/pwg/brillig.rs index 5ec3224dbaa..a5f5783478e 100644 --- a/acvm-repo/acvm/src/pwg/brillig.rs +++ b/acvm-repo/acvm/src/pwg/brillig.rs @@ -6,13 +6,12 @@ use acir::{ brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, opcodes::BlockId, ErrorSelector, OpcodeLocation, RawAssertionPayload, ResolvedAssertionPayload, - STRING_ERROR_SELECTOR, }, native_types::WitnessMap, AcirField, }; use acvm_blackbox_solver::BlackBoxFunctionSolver; -use brillig_vm::{FailureReason, MemoryValue, VMStatus, VM}; +use brillig_vm::{BrilligProfilingSamples, FailureReason, MemoryValue, VMStatus, VM}; use serde::{Deserialize, Serialize}; use crate::{pwg::OpcodeNotSolvable, OpcodeResolutionError}; @@ -58,6 +57,7 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { /// Constructs a solver for a Brillig block given the bytecode and initial /// witness. + #[allow(clippy::too_many_arguments)] pub(crate) fn new_call( initial_witness: &WitnessMap, memory: &HashMap>, @@ -66,9 +66,16 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { bb_solver: &'b B, acir_index: usize, brillig_function_id: BrilligFunctionId, + profiling_active: bool, ) -> Result> { - let vm = - Self::setup_brillig_vm(initial_witness, memory, inputs, brillig_bytecode, bb_solver)?; + let vm = Self::setup_brillig_vm( + initial_witness, + memory, + inputs, + brillig_bytecode, + bb_solver, + profiling_active, + )?; Ok(Self { vm, acir_index, function_id: brillig_function_id }) } @@ -78,6 +85,7 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { inputs: &[BrilligInputs], brillig_bytecode: &'b [BrilligOpcode], bb_solver: &'b B, + profiling_active: bool, ) -> Result, OpcodeResolutionError> { // Set input values let mut calldata: Vec = Vec::new(); @@ -125,7 +133,7 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { // Instantiate a Brillig VM given the solved calldata // along with the Brillig bytecode. - let vm = VM::new(calldata, brillig_bytecode, vec![], bb_solver); + let vm = VM::new(calldata, brillig_bytecode, vec![], bb_solver, profiling_active); Ok(vm) } @@ -203,6 +211,25 @@ impl<'b, B: BlackBoxFunctionSolver, F: AcirField> BrilligSolver<'b, F, B> { self, witness: &mut WitnessMap, outputs: &[BrilligOutputs], + ) -> Result<(), OpcodeResolutionError> { + assert!(!self.vm.is_profiling_active(), "Expected VM profiling to not be active"); + self.finalize_inner(witness, outputs) + } + + pub(crate) fn finalize_with_profiling( + mut self, + witness: &mut WitnessMap, + outputs: &[BrilligOutputs], + ) -> Result> { + assert!(self.vm.is_profiling_active(), "Expected VM profiling to be active"); + self.finalize_inner(witness, outputs)?; + Ok(self.vm.take_profiling_samples()) + } + + fn finalize_inner( + &self, + witness: &mut WitnessMap, + outputs: &[BrilligOutputs], ) -> Result<(), OpcodeResolutionError> { // Finish the Brillig execution by writing the outputs to the witness map let vm_status = self.vm.get_status(); @@ -279,25 +306,10 @@ fn extract_failure_payload_from_memory( .expect("Error selector is not u64"), ); - match error_selector { - STRING_ERROR_SELECTOR => { - // If the error selector is 0, it means the error is a string - let string = revert_values_iter - .map(|&memory_value| { - let as_u8: u8 = memory_value.try_into().expect("String item is not u8"); - as_u8 as char - }) - .collect(); - Some(ResolvedAssertionPayload::String(string)) - } - _ => { - // If the error selector is not 0, it means the error is a custom error - Some(ResolvedAssertionPayload::Raw(RawAssertionPayload { - selector: error_selector, - data: revert_values_iter.map(|value| value.to_field()).collect(), - })) - } - } + Some(ResolvedAssertionPayload::Raw(RawAssertionPayload { + selector: error_selector, + data: revert_values_iter.map(|value| value.to_field()).collect(), + })) } } diff --git a/acvm-repo/acvm/src/pwg/directives/mod.rs b/acvm-repo/acvm/src/pwg/directives/mod.rs deleted file mode 100644 index d7bee88c278..00000000000 --- a/acvm-repo/acvm/src/pwg/directives/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -use acir::{circuit::directives::Directive, native_types::WitnessMap, AcirField}; -use num_bigint::BigUint; - -use crate::OpcodeResolutionError; - -use super::{get_value, insert_value, ErrorLocation}; - -/// Attempts to solve the [`Directive`] opcode `directive`. -/// If successful, `initial_witness` will be mutated to contain the new witness assignment. -/// -/// Returns `Ok(OpcodeResolution)` to signal whether the directive was successful solved. -/// -/// Returns `Err(OpcodeResolutionError)` if a circuit constraint is unsatisfied. -pub(crate) fn solve_directives( - initial_witness: &mut WitnessMap, - directive: &Directive, -) -> Result<(), OpcodeResolutionError> { - match directive { - Directive::ToLeRadix { a, b, radix } => { - let value_a = get_value(a, initial_witness)?; - let big_integer = BigUint::from_bytes_be(&value_a.to_be_bytes()); - - // Decompose the integer into its radix digits in little endian form. - let decomposed_integer = big_integer.to_radix_le(*radix); - - if b.len() < decomposed_integer.len() { - return Err(OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: ErrorLocation::Unresolved, - payload: None, - }); - } - - for (i, witness) in b.iter().enumerate() { - // Fetch the `i'th` digit from the decomposed integer list - // and convert it to a field element. - // If it is not available, which can happen when the decomposed integer - // list is shorter than the witness list, we return 0. - let value = match decomposed_integer.get(i) { - Some(digit) => F::from_be_bytes_reduce(&[*digit]), - None => F::zero(), - }; - - insert_value(witness, value, initial_witness)?; - } - - Ok(()) - } - } -} diff --git a/acvm-repo/acvm/src/pwg/mod.rs b/acvm-repo/acvm/src/pwg/mod.rs index c73893ceea6..f9188cca700 100644 --- a/acvm-repo/acvm/src/pwg/mod.rs +++ b/acvm-repo/acvm/src/pwg/mod.rs @@ -10,7 +10,7 @@ use acir::{ AcirFunctionId, BlockId, ConstantOrWitnessEnum, FunctionInput, InvalidInputBitSize, }, AssertionPayload, ErrorSelector, ExpressionOrMemory, Opcode, OpcodeLocation, - RawAssertionPayload, ResolvedAssertionPayload, STRING_ERROR_SELECTOR, + RawAssertionPayload, ResolvedAssertionPayload, }, native_types::{Expression, Witness, WitnessMap}, AcirField, BlackBoxFunc, @@ -18,8 +18,7 @@ use acir::{ use acvm_blackbox_solver::BlackBoxResolutionError; use self::{ - arithmetic::ExpressionSolver, blackbox::bigint::AcvmBigIntSolver, directives::solve_directives, - memory_op::MemoryOpSolver, + arithmetic::ExpressionSolver, blackbox::bigint::AcvmBigIntSolver, memory_op::MemoryOpSolver, }; use crate::BlackBoxFunctionSolver; @@ -29,8 +28,6 @@ use thiserror::Error; pub(crate) mod arithmetic; // Brillig bytecode pub(crate) mod brillig; -// Directives -pub(crate) mod directives; // black box functions pub(crate) mod blackbox; mod memory_op; @@ -168,6 +165,14 @@ impl From for OpcodeResolutionError { } } +pub type ProfilingSamples = Vec; + +#[derive(Default)] +pub struct ProfilingSample { + pub call_stack: Vec, + pub brillig_function_id: Option, +} + pub struct ACVM<'a, F, B: BlackBoxFunctionSolver> { status: ACVMStatus, @@ -198,6 +203,10 @@ pub struct ACVM<'a, F, B: BlackBoxFunctionSolver> { unconstrained_functions: &'a [BrilligBytecode], assertion_payloads: &'a [(OpcodeLocation, AssertionPayload)], + + profiling_active: bool, + + profiling_samples: ProfilingSamples, } impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { @@ -222,9 +231,16 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { acir_call_results: Vec::default(), unconstrained_functions, assertion_payloads, + profiling_active: false, + profiling_samples: Vec::new(), } } + // Enable profiling + pub fn with_profiler(&mut self, profiling_active: bool) { + self.profiling_active = profiling_active; + } + /// Returns a reference to the current state of the ACVM's [`WitnessMap`]. /// /// Once execution has completed, the witness map can be extracted using [`ACVM::finalize`] @@ -246,6 +262,10 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { self.instruction_pointer } + pub fn take_profiling_samples(&mut self) -> ProfilingSamples { + std::mem::take(&mut self.profiling_samples) + } + /// Finalize the ACVM execution, returning the resulting [`WitnessMap`]. pub fn finalize(self) -> WitnessMap { if self.status != ACVMStatus::Solved { @@ -339,7 +359,6 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { pub fn solve_opcode(&mut self) -> ACVMStatus { let opcode = &self.opcodes[self.instruction_pointer]; - let resolution = match opcode { Opcode::AssertZero(expr) => ExpressionSolver::solve(&mut self.witness_map, expr), Opcode::BlackBoxFuncCall(bb_func) => blackbox::solve( @@ -348,7 +367,6 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { bb_func, &mut self.bigint_solver, ), - Opcode::Directive(directive) => solve_directives(&mut self.witness_map, directive), Opcode::MemoryInit { block_id, init, .. } => { let solver = self.block_solvers.entry(*block_id).or_default(); solver.init(init, &self.witness_map) @@ -422,59 +440,32 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { &self, location: OpcodeLocation, ) -> Option> { - let (_, found_assertion_payload) = + let (_, assertion_descriptor) = self.assertion_payloads.iter().find(|(loc, _)| location == *loc)?; - match found_assertion_payload { - AssertionPayload::StaticString(string) => { - Some(ResolvedAssertionPayload::String(string.clone())) - } - AssertionPayload::Dynamic(error_selector, expression) => { - let mut fields = vec![]; - for expr in expression { - match expr { - ExpressionOrMemory::Expression(expr) => { - let value = get_value(expr, &self.witness_map).ok()?; - fields.push(value); - } - ExpressionOrMemory::Memory(block_id) => { - let memory_block = self.block_solvers.get(block_id)?; - fields.extend((0..memory_block.block_len).map(|memory_index| { - *memory_block - .block_value - .get(&memory_index) - .expect("All memory is initialized on creation") - })); - } - } + let mut fields = Vec::new(); + for expr in assertion_descriptor.payload.iter() { + match expr { + ExpressionOrMemory::Expression(expr) => { + let value = get_value(expr, &self.witness_map).ok()?; + fields.push(value); + } + ExpressionOrMemory::Memory(block_id) => { + let memory_block = self.block_solvers.get(block_id)?; + fields.extend((0..memory_block.block_len).map(|memory_index| { + *memory_block + .block_value + .get(&memory_index) + .expect("All memory is initialized on creation") + })); } - let error_selector = ErrorSelector::new(*error_selector); - - Some(match error_selector { - STRING_ERROR_SELECTOR => { - // If the error selector is 0, it means the error is a string - let string = fields - .iter() - .map(|field| { - let as_u8: u8 = field - .try_to_u64() - .expect("String character doesn't fit in u64") - .try_into() - .expect("String character doesn't fit in u8"); - as_u8 as char - }) - .collect(); - ResolvedAssertionPayload::String(string) - } - _ => { - // If the error selector is not 0, it means the error is a custom error - ResolvedAssertionPayload::Raw(RawAssertionPayload { - selector: error_selector, - data: fields, - }) - } - }) } } + let error_selector = ErrorSelector::new(assertion_descriptor.error_selector); + + Some(ResolvedAssertionPayload::Raw(RawAssertionPayload { + selector: error_selector, + data: fields, + })) } fn solve_brillig_call_opcode( @@ -503,10 +494,11 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { self.backend, self.instruction_pointer, *id, + self.profiling_active, )?, }; - let result = solver.solve().map_err(|err| self.map_brillig_error(err))?; + let result = solver.solve()?; match result { BrilligSolverStatus::ForeignCallWait(foreign_call) => { @@ -519,34 +511,30 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { } BrilligSolverStatus::Finished => { // Write execution outputs - solver.finalize(&mut self.witness_map, outputs)?; - Ok(None) - } - } - } - - fn map_brillig_error(&self, mut err: OpcodeResolutionError) -> OpcodeResolutionError { - match &mut err { - OpcodeResolutionError::BrilligFunctionFailed { call_stack, payload, .. } => { - // Some brillig errors have static strings as payloads, we can resolve them here - let last_location = - call_stack.last().expect("Call stacks should have at least one item"); - let assertion_descriptor = - self.assertion_payloads.iter().find_map(|(loc, payload)| { - if loc == last_location { - Some(payload) - } else { - None - } + if self.profiling_active { + let profiling_info = + solver.finalize_with_profiling(&mut self.witness_map, outputs)?; + profiling_info.into_iter().for_each(|sample| { + let mapped = + sample.call_stack.into_iter().map(|loc| OpcodeLocation::Brillig { + acir_index: self.instruction_pointer, + brillig_index: loc, + }); + self.profiling_samples.push(ProfilingSample { + call_stack: std::iter::once(OpcodeLocation::Acir( + self.instruction_pointer, + )) + .chain(mapped) + .collect(), + brillig_function_id: Some(*id), + }); }); - - if let Some(AssertionPayload::StaticString(string)) = assertion_descriptor { - *payload = Some(ResolvedAssertionPayload::String(string.clone())); + } else { + solver.finalize(&mut self.witness_map, outputs)?; } - err + Ok(None) } - _ => err, } } @@ -575,6 +563,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> ACVM<'a, F, B> { self.backend, self.instruction_pointer, *id, + self.profiling_active, ); match solver { Ok(solver) => StepResult::IntoBrillig(solver), diff --git a/acvm-repo/acvm/tests/solver.rs b/acvm-repo/acvm/tests/solver.rs index 6ad52999820..8b164b7c0f2 100644 --- a/acvm-repo/acvm/tests/solver.rs +++ b/acvm-repo/acvm/tests/solver.rs @@ -1,10 +1,10 @@ use std::collections::{BTreeMap, HashSet}; use std::sync::Arc; -use acir::brillig::{BitSize, IntegerBitSize}; +use acir::brillig::{BitSize, HeapVector, IntegerBitSize}; use acir::{ acir_field::GenericFieldElement, - brillig::{BinaryFieldOp, HeapArray, MemoryAddress, Opcode as BrilligOpcode, ValueOrArray}, + brillig::{BinaryFieldOp, MemoryAddress, Opcode as BrilligOpcode, ValueOrArray}, circuit::{ brillig::{BrilligBytecode, BrilligFunctionId, BrilligInputs, BrilligOutputs}, opcodes::{BlackBoxFuncCall, BlockId, BlockType, FunctionInput, MemOp}, @@ -77,13 +77,6 @@ fn inversion_brillig_oracle_equivalence() { let w_x_plus_y = Witness(6); let w_equal_res = Witness(7); - let equal_opcode = BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Equals, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(2), - }; - let opcodes = vec![ Opcode::BrilligCall { id: BrilligFunctionId(0), @@ -122,33 +115,51 @@ fn inversion_brillig_oracle_equivalence() { }), ]; + let equal_opcode = BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Equals, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), + }; + + let zero_usize = MemoryAddress::direct(3); + let two_usize = MemoryAddress::direct(4); + let three_usize = MemoryAddress::direct(5); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: two_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(2u64), }, BrilligOpcode::Const { - destination: MemoryAddress(1), + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(3u64), }, BrilligOpcode::CalldataCopy { - destination_address: MemoryAddress(0), - size_address: MemoryAddress(0), - offset_address: MemoryAddress(1), + destination_address: MemoryAddress::direct(0), + size_address: two_usize, + offset_address: zero_usize, }, equal_opcode, // Oracles are named 'foreign calls' in brillig BrilligOpcode::ForeignCall { function: "invert".into(), - destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(1))], + destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(1))], destination_value_types: vec![HeapValueType::field()], - inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], + inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 3 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: three_usize }, + }, ], }; @@ -216,13 +227,6 @@ fn double_inversion_brillig_oracle() { let w_ij_oracle = Witness(10); let w_i_plus_j = Witness(11); - let equal_opcode = BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Equals, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(4), - }; - let opcodes = vec![ Opcode::BrilligCall { id: BrilligFunctionId(0), @@ -268,40 +272,58 @@ fn double_inversion_brillig_oracle() { }), ]; + let zero_usize = MemoryAddress::direct(5); + let three_usize = MemoryAddress::direct(6); + let five_usize = MemoryAddress::direct(7); + + let equal_opcode = BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Equals, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(4), + }; + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(3u64), }, BrilligOpcode::Const { - destination: MemoryAddress(1), + destination: five_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(5u64), }, BrilligOpcode::CalldataCopy { - destination_address: MemoryAddress(0), - size_address: MemoryAddress(0), - offset_address: MemoryAddress(1), + destination_address: MemoryAddress::direct(0), + size_address: three_usize, + offset_address: zero_usize, }, equal_opcode, // Oracles are named 'foreign calls' in brillig BrilligOpcode::ForeignCall { function: "invert".into(), - destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(1))], + destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(1))], destination_value_types: vec![HeapValueType::field()], - inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], + inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], input_value_types: vec![HeapValueType::field()], }, BrilligOpcode::ForeignCall { function: "invert".into(), - destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(3))], + destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(3))], destination_value_types: vec![HeapValueType::field()], - inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(2))], + inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(2))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 5 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: five_usize }, + }, ], }; @@ -386,38 +408,49 @@ fn oracle_dependent_execution() { let w_x_inv = Witness(3); let w_y_inv = Witness(4); + let zero_usize = MemoryAddress::direct(4); + let three_usize = MemoryAddress::direct(5); + let four_usize = MemoryAddress::direct(6); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(3u64), }, BrilligOpcode::Const { - destination: MemoryAddress(1), + destination: four_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(4u64), }, BrilligOpcode::CalldataCopy { - destination_address: MemoryAddress(0), - size_address: MemoryAddress(0), - offset_address: MemoryAddress(1), + destination_address: MemoryAddress::direct(0), + size_address: three_usize, + offset_address: zero_usize, }, // Oracles are named 'foreign calls' in brillig BrilligOpcode::ForeignCall { function: "invert".into(), - destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(1))], + destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(1))], destination_value_types: vec![HeapValueType::field()], - inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], + inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], input_value_types: vec![HeapValueType::field()], }, BrilligOpcode::ForeignCall { function: "invert".into(), - destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(3))], + destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(3))], destination_value_types: vec![HeapValueType::field()], - inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(2))], + inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(2))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 4 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: four_usize }, + }, ], }; @@ -522,35 +555,35 @@ fn brillig_oracle_predicate() { let equal_opcode = BrilligOpcode::BinaryFieldOp { op: BinaryFieldOp::Equals, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(2), + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), }; let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(2u64), }, BrilligOpcode::Const { - destination: MemoryAddress(1), + destination: MemoryAddress::direct(1), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, BrilligOpcode::CalldataCopy { - destination_address: MemoryAddress(0), - size_address: MemoryAddress(0), - offset_address: MemoryAddress(1), + destination_address: MemoryAddress::direct(0), + size_address: MemoryAddress::direct(0), + offset_address: MemoryAddress::direct(1), }, equal_opcode, // Oracles are named 'foreign calls' in brillig BrilligOpcode::ForeignCall { function: "invert".into(), - destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(1))], + destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(1))], destination_value_types: vec![HeapValueType::field()], - inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::from(0))], + inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], input_value_types: vec![HeapValueType::field()], }, ], @@ -649,36 +682,51 @@ fn unsatisfied_opcode_resolved_brillig() { let w_result = Witness(6); let calldata_copy_opcode = BrilligOpcode::CalldataCopy { - destination_address: MemoryAddress(0), - size_address: MemoryAddress(0), - offset_address: MemoryAddress(1), + destination_address: MemoryAddress::direct(0), + size_address: MemoryAddress::direct(0), + offset_address: MemoryAddress::direct(1), }; let equal_opcode = BrilligOpcode::BinaryFieldOp { op: BinaryFieldOp::Equals, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(2), + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), }; // Jump pass the trap if the values are equal, else // jump to the trap - let location_of_stop = 3; + let location_of_stop = 7; let jmp_if_opcode = - BrilligOpcode::JumpIf { condition: MemoryAddress::from(2), location: location_of_stop }; + BrilligOpcode::JumpIf { condition: MemoryAddress::direct(2), location: location_of_stop }; - let trap_opcode = BrilligOpcode::Trap { revert_data: HeapArray::default() }; - let stop_opcode = BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }; + let trap_opcode = BrilligOpcode::Trap { + revert_data: HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(3), + }, + }; + let stop_opcode = BrilligOpcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(3), + }, + }; let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(2u64), }, BrilligOpcode::Const { - destination: MemoryAddress(1), + destination: MemoryAddress::direct(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: MemoryAddress::direct(3), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, @@ -739,7 +787,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: 5 }] + call_stack: vec![OpcodeLocation::Brillig { acir_index: 0, brillig_index: 6 }] }), "The first opcode is not satisfiable, expected an error indicating this" ); @@ -1099,45 +1147,6 @@ fn blake3_op( }) } -// variable inputs -// 32 outputs -fn keccak256_op( - function_inputs_and_outputs: (Vec>, Vec), -) -> Result, OpcodeResolutionError> { - let (function_inputs, outputs) = function_inputs_and_outputs; - let function_inputs_len = function_inputs.len(); - Ok(BlackBoxFuncCall::Keccak256 { - inputs: function_inputs, - var_message_size: FunctionInput::constant( - function_inputs_len.into(), - FieldElement::max_num_bits(), - )?, - outputs: outputs.try_into().expect("Keccak256 returns 32 outputs"), - }) -} - -// var_message_size is the number of bytes to take -// from the input. Note: if `var_message_size` -// is more than the number of bytes in the input, -// then an error is returned. -// -// variable inputs -// 32 outputs -fn keccak256_invalid_message_size_op( - function_inputs_and_outputs: (Vec>, Vec), -) -> Result, OpcodeResolutionError> { - let (function_inputs, outputs) = function_inputs_and_outputs; - let function_inputs_len = function_inputs.len(); - Ok(BlackBoxFuncCall::Keccak256 { - inputs: function_inputs, - var_message_size: FunctionInput::constant( - (function_inputs_len - 1).into(), - FieldElement::max_num_bits(), - )?, - outputs: outputs.try_into().expect("Keccak256 returns 32 outputs"), - }) -} - // 25 inputs // 25 outputs fn keccakf1600_op( @@ -1489,19 +1498,6 @@ fn blake3_zeros() { assert_eq!(results, Ok(expected_results)); } -#[test] -fn keccak256_zeros() { - let results = solve_array_input_blackbox_call(vec![], 32, None, keccak256_op); - let expected_results: Vec<_> = vec![ - 197, 210, 70, 1, 134, 247, 35, 60, 146, 126, 125, 178, 220, 199, 3, 192, 229, 0, 182, 83, - 202, 130, 39, 59, 123, 250, 216, 4, 93, 133, 164, 112, - ] - .into_iter() - .map(|x: u128| FieldElement::from(x)) - .collect(); - assert_eq!(results, Ok(expected_results)); -} - #[test] fn keccakf1600_zeros() { let results = solve_array_input_blackbox_call( @@ -1642,24 +1638,6 @@ proptest! { prop_assert!(result, "{}", message); } - #[test] - fn keccak256_injective(inputs_distinct_inputs in any_distinct_inputs(Some(8), 0, 32)) { - let (inputs, distinct_inputs) = inputs_distinct_inputs; - let (result, message) = prop_assert_injective(inputs, distinct_inputs, 32, Some(8), keccak256_op); - prop_assert!(result, "{}", message); - } - - // TODO(https://github.com/noir-lang/noir/issues/5689): doesn't fail with a user error - // The test failing with "not injective" demonstrates that it returns constant output instead - // of failing with a user error. - #[test] - #[should_panic(expected = "Test failed: not injective")] - fn keccak256_invalid_message_size_fails(inputs_distinct_inputs in any_distinct_inputs(Some(8), 0, 32)) { - let (inputs, distinct_inputs) = inputs_distinct_inputs; - let (result, message) = prop_assert_injective(inputs, distinct_inputs, 32, Some(8), keccak256_invalid_message_size_op); - prop_assert!(result, "{}", message); - } - #[test] fn keccakf1600_injective(inputs_distinct_inputs in any_distinct_inputs(Some(8), 25, 25)) { let (inputs, distinct_inputs) = inputs_distinct_inputs; diff --git a/acvm-repo/acvm_js/Cargo.toml b/acvm-repo/acvm_js/Cargo.toml index b5b55dbb91a..bd536817428 100644 --- a/acvm-repo/acvm_js/Cargo.toml +++ b/acvm-repo/acvm_js/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_js" description = "Typescript wrapper around the ACVM allowing execution of ACIR code" # x-release-please-start-version -version = "0.50.0" +version = "1.0.0-beta.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acvm_js/package.json b/acvm-repo/acvm_js/package.json index 95b8a46456f..904263b5e27 100644 --- a/acvm-repo/acvm_js/package.json +++ b/acvm-repo/acvm_js/package.json @@ -1,6 +1,6 @@ { "name": "@noir-lang/acvm_js", - "version": "0.50.0", + "version": "1.0.0-beta.0", "publishConfig": { "access": "public" }, diff --git a/acvm-repo/acvm_js/src/black_box_solvers.rs b/acvm-repo/acvm_js/src/black_box_solvers.rs index 6046d52943c..0e35851ee78 100644 --- a/acvm-repo/acvm_js/src/black_box_solvers.rs +++ b/acvm-repo/acvm_js/src/black_box_solvers.rs @@ -37,12 +37,6 @@ pub fn blake2s256(inputs: &[u8]) -> Vec { acvm::blackbox_solver::blake2s(inputs).unwrap().into() } -/// Calculates the Keccak256 hash of the input bytes -#[wasm_bindgen] -pub fn keccak256(inputs: &[u8]) -> Vec { - acvm::blackbox_solver::keccak256(inputs).unwrap().into() -} - /// Verifies a ECDSA signature over the secp256k1 curve. #[wasm_bindgen] pub fn ecdsa_secp256k1_verify( diff --git a/acvm-repo/acvm_js/src/lib.rs b/acvm-repo/acvm_js/src/lib.rs index 8fe64afbba9..e2468e6d939 100644 --- a/acvm-repo/acvm_js/src/lib.rs +++ b/acvm-repo/acvm_js/src/lib.rs @@ -17,8 +17,7 @@ mod logging; mod public_witness; pub use black_box_solvers::{ - and, blake2s256, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccak256, sha256_compression, - xor, + and, blake2s256, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, sha256_compression, xor, }; pub use build_info::build_info; pub use compression::{ diff --git a/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts b/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts index 9dc5be2c682..b99fe9e3d88 100644 --- a/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts +++ b/acvm-repo/acvm_js/test/browser/black_box_solvers.test.ts @@ -4,7 +4,6 @@ import initACVM, { blake2s256, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, - keccak256, sha256_compression, xor, } from '@noir-lang/acvm_js'; @@ -51,16 +50,6 @@ it('successfully calculates the blake2s256 hash', async () => { } }); -it('successfully calculates the keccak256 hash', async () => { - const { keccak256_test_cases } = await import('../shared/black_box_solvers'); - - for (const testCase of keccak256_test_cases) { - const [preimage, expectedResult] = testCase; - const hash = keccak256(preimage); - hash.forEach((value, index) => expect(value).to.be.eq(expectedResult.at(index))); - } -}); - it('successfully verifies secp256k1 ECDSA signatures', async () => { const { ecdsa_secp256k1_test_cases } = await import('../shared/black_box_solvers'); diff --git a/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts b/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts index aaa82f8f1e5..4d8f0acbd38 100644 --- a/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts +++ b/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts @@ -85,16 +85,6 @@ it('successfully executes a MultiScalarMul opcode', async () => { expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); }); -it('successfully executes a SchnorrVerify opcode', async () => { - const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/schnorr_verify'); - - const solvedWitness: WitnessMap = await executeCircuit(bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); - - expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); -}); - it('successfully executes a MemoryOp opcode', async () => { const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/memory_op'); diff --git a/acvm-repo/acvm_js/test/node/black_box_solvers.test.ts b/acvm-repo/acvm_js/test/node/black_box_solvers.test.ts index fc998ced5a5..74553f6b692 100644 --- a/acvm-repo/acvm_js/test/node/black_box_solvers.test.ts +++ b/acvm-repo/acvm_js/test/node/black_box_solvers.test.ts @@ -4,7 +4,6 @@ import { blake2s256, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, - keccak256, sha256_compression, xor, } from '@noir-lang/acvm_js'; @@ -47,28 +46,6 @@ it('successfully calculates the blake2s256 hash', async () => { } }); -it('successfully calculates the keccak256 hash', async () => { - const { keccak256_test_cases } = await import('../shared/black_box_solvers'); - - for (const testCase of keccak256_test_cases) { - const [preimage, expectedResult] = testCase; - const hash = keccak256(preimage); - hash.forEach((value, index) => expect(value).to.be.eq(expectedResult.at(index))); - } -}); - -// it("successfully calculates the hash_to_field_128_security field", async () => { -// const { hash_to_field_128_security_test_cases } = await import( -// "../shared/black_box_solvers" -// ); - -// for (const testCase of hash_to_field_128_security_test_cases) { -// const [preimage, expectedResult] = testCase; -// const hashField = hash_to_field_128_security(preimage); -// expect(hashField).to.be.eq(expectedResult); -// } -// }); - it('successfully verifies secp256k1 ECDSA signatures', async () => { const { ecdsa_secp256k1_test_cases } = await import('../shared/black_box_solvers'); diff --git a/acvm-repo/acvm_js/test/node/execute_circuit.test.ts b/acvm-repo/acvm_js/test/node/execute_circuit.test.ts index 120ad0fa738..67f7de2129c 100644 --- a/acvm-repo/acvm_js/test/node/execute_circuit.test.ts +++ b/acvm-repo/acvm_js/test/node/execute_circuit.test.ts @@ -86,16 +86,6 @@ it('successfully executes a MultiScalarMul opcode', async () => { expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); }); -it('successfully executes a SchnorrVerify opcode', async () => { - const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/schnorr_verify'); - - const solvedWitness: WitnessMap = await executeCircuit(bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); - - expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); -}); - it('successfully executes a MemoryOp opcode', async () => { const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/memory_op'); diff --git a/acvm-repo/acvm_js/test/shared/addition.ts b/acvm-repo/acvm_js/test/shared/addition.ts index 820a415acf3..2b8124e77d7 100644 --- a/acvm-repo/acvm_js/test/shared/addition.ts +++ b/acvm-repo/acvm_js/test/shared/addition.ts @@ -3,10 +3,10 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `addition_circuit` 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, 144, 65, 14, 128, 32, 12, 4, 65, 124, 80, 75, 91, 104, 111, 126, 69, 34, 252, - 255, 9, 106, 228, 64, 162, 55, 153, 164, 217, 158, 38, 155, 245, 238, 97, 189, 206, 187, 55, 161, 231, 214, 19, 254, - 129, 126, 162, 107, 25, 92, 4, 137, 185, 230, 88, 145, 112, 135, 104, 69, 5, 88, 74, 82, 84, 20, 149, 35, 42, 81, 85, - 214, 108, 197, 50, 24, 50, 85, 108, 98, 212, 186, 44, 204, 235, 5, 183, 99, 233, 46, 63, 252, 110, 216, 56, 184, 15, - 78, 146, 74, 173, 20, 141, 1, 0, 0, + 255, 9, 106, 228, 64, 194, 81, 38, 105, 182, 167, 201, 102, 189, 251, 216, 159, 243, 110, 38, 244, 60, 122, 194, 63, + 208, 47, 116, 109, 131, 139, 32, 49, 215, 28, 43, 18, 158, 16, 173, 168, 0, 75, 73, 138, 138, 162, 114, 69, 37, 170, + 202, 154, 173, 88, 6, 67, 166, 138, 77, 140, 90, 151, 133, 117, 189, 224, 117, 108, 221, 229, 135, 223, 13, 27, 135, + 121, 106, 119, 3, 58, 173, 124, 163, 140, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ diff --git a/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index 60e4c8d5829..24fbc1a921a 100644 --- a/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,14 +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, 85, 81, 14, 194, 48, 8, 133, 118, 186, 53, 241, 207, 11, 152, 232, 1, 58, 189, - 128, 119, 49, 254, 105, 244, 211, 227, 59, 50, 154, 49, 214, 100, 31, 163, 201, 246, 146, 133, 174, 5, 10, 15, 72, 17, - 122, 52, 221, 135, 188, 222, 177, 116, 44, 105, 223, 195, 24, 73, 247, 206, 50, 46, 67, 139, 118, 190, 98, 169, 24, - 221, 6, 98, 244, 5, 98, 4, 81, 255, 21, 214, 219, 178, 46, 166, 252, 249, 204, 252, 84, 208, 207, 215, 158, 255, 107, - 150, 141, 38, 154, 140, 28, 76, 7, 111, 132, 212, 61, 65, 201, 116, 86, 217, 101, 115, 11, 226, 62, 99, 223, 145, 88, - 56, 205, 228, 102, 127, 239, 53, 6, 69, 184, 97, 78, 109, 96, 127, 37, 106, 81, 11, 126, 100, 103, 17, 14, 48, 116, - 213, 227, 243, 254, 190, 158, 63, 175, 40, 149, 102, 132, 179, 88, 95, 212, 57, 42, 59, 109, 43, 33, 31, 140, 156, 46, - 102, 244, 230, 124, 31, 97, 104, 141, 244, 48, 253, 1, 180, 46, 168, 159, 181, 6, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 205, 14, 130, 48, 12, 238, 54, 20, 136, 222, 124, 1, 19, 125, 128, 161, + 241, 238, 187, 24, 111, 26, 61, 250, 248, 178, 216, 198, 89, 26, 56, 216, 18, 248, 146, 165, 12, 218, 175, 255, 193, + 193, 7, 85, 123, 28, 62, 23, 40, 61, 202, 244, 62, 192, 47, 72, 247, 140, 50, 254, 135, 198, 233, 113, 69, 171, 24, + 253, 12, 98, 12, 6, 49, 66, 214, 255, 9, 246, 91, 179, 47, 170, 245, 11, 194, 254, 164, 221, 90, 180, 103, 137, 247, + 18, 101, 197, 11, 157, 140, 60, 116, 23, 47, 7, 13, 207, 10, 101, 45, 124, 87, 76, 232, 88, 51, 191, 202, 252, 145, + 138, 177, 133, 254, 124, 109, 243, 60, 68, 226, 15, 38, 252, 177, 33, 254, 194, 168, 79, 37, 171, 87, 158, 75, 238, + 119, 13, 223, 1, 188, 60, 238, 207, 219, 245, 21, 4, 83, 110, 158, 176, 99, 247, 189, 80, 178, 33, 14, 66, 254, 159, + 233, 211, 119, 130, 254, 144, 205, 88, 163, 98, 180, 18, 167, 13, 116, 65, 190, 222, 250, 76, 4, 233, 188, 7, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/acvm-repo/acvm_js/test/shared/foreign_call.ts b/acvm-repo/acvm_js/test/shared/foreign_call.ts index 9bf57535c87..da0b9974c61 100644 --- a/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,11 +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, 81, 73, 10, 192, 48, 8, 140, 165, 91, 160, 183, 126, 196, 254, 160, 159, 233, - 161, 151, 30, 74, 200, 251, 19, 136, 130, 132, 196, 75, 28, 16, 199, 17, 212, 65, 112, 5, 123, 14, 32, 190, 80, 230, - 90, 130, 181, 155, 50, 142, 225, 2, 187, 89, 40, 239, 157, 106, 2, 82, 116, 138, 51, 118, 239, 171, 222, 108, 232, - 218, 139, 125, 198, 179, 113, 83, 188, 29, 57, 86, 226, 239, 23, 159, 63, 104, 63, 238, 213, 45, 237, 108, 244, 18, - 195, 174, 252, 193, 92, 2, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 203, 10, 128, 48, 12, 179, 243, 57, 240, 230, 143, 108, 127, 224, 207, + 120, 240, 226, 65, 196, 239, 119, 98, 11, 101, 100, 94, 214, 64, 73, 26, 88, 73, 24, 53, 31, 166, 52, 196, 186, 99, + 150, 93, 67, 188, 149, 57, 212, 33, 146, 221, 173, 160, 243, 186, 92, 144, 54, 127, 138, 245, 204, 62, 243, 95, 110, + 13, 195, 122, 144, 207, 240, 126, 28, 65, 71, 7, 250, 206, 105, 6, 214, 251, 113, 111, 231, 133, 190, 93, 191, 40, + 237, 37, 127, 1, 190, 36, 121, 0, 128, 254, 118, 42, 127, 2, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/acvm-repo/acvm_js/test/shared/memory_op.ts b/acvm-repo/acvm_js/test/shared/memory_op.ts index f7443c2258b..2f0fbfb85f1 100644 --- a/acvm-repo/acvm_js/test/shared/memory_op.ts +++ b/acvm-repo/acvm_js/test/shared/memory_op.ts @@ -1,9 +1,9 @@ // See `memory_op_circuit` 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, 82, 65, 10, 0, 32, 8, 211, 180, 255, 216, 15, 250, 255, 171, 10, 82, 176, 232, - 150, 30, 26, 200, 118, 144, 49, 135, 8, 11, 117, 14, 169, 102, 229, 162, 140, 78, 219, 206, 137, 174, 44, 111, 104, - 217, 190, 24, 236, 75, 113, 94, 146, 93, 174, 252, 86, 46, 71, 223, 78, 46, 104, 129, 253, 155, 45, 60, 195, 5, 3, 89, - 11, 161, 73, 39, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 144, 75, 10, 0, 32, 8, 68, 253, 117, 31, 187, 65, 247, 63, 85, 65, 10, 82, + 203, 116, 209, 128, 60, 221, 12, 227, 32, 108, 181, 53, 108, 187, 147, 140, 24, 118, 231, 169, 97, 212, 55, 245, 106, + 95, 76, 246, 229, 60, 47, 173, 46, 87, 127, 43, 87, 178, 127, 231, 16, 148, 194, 29, 195, 11, 220, 154, 119, 139, 115, + 25, 38, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts b/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts index f23847a75fc..fac77e4ee27 100644 --- a/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts +++ b/acvm-repo/acvm_js/test/shared/multi_scalar_mul.ts @@ -1,8 +1,8 @@ // See `multi_scalar_mul_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 141, 11, 10, 0, 32, 8, 67, 43, 181, 15, 221, 255, 186, 145, 210, 130, 149, 240, - 112, 234, 212, 156, 78, 12, 39, 67, 71, 158, 142, 80, 29, 44, 228, 66, 90, 168, 119, 189, 74, 115, 131, 174, 78, 115, - 58, 124, 70, 254, 130, 59, 74, 253, 68, 255, 255, 221, 39, 54, 29, 134, 27, 102, 193, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 77, 9, 10, 0, 48, 8, 114, 107, 231, 255, 255, 59, 86, 204, 64, 22, 136, 102, + 89, 5, 175, 182, 163, 80, 7, 47, 135, 73, 31, 56, 228, 42, 218, 196, 203, 221, 38, 243, 78, 61, 28, 147, 119, 65, 31, + 146, 53, 230, 210, 135, 252, 255, 179, 90, 23, 212, 196, 199, 187, 192, 0, 0, 0, ]); export const initialWitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/acvm-repo/acvm_js/test/shared/nested_acir_call.ts b/acvm-repo/acvm_js/test/shared/nested_acir_call.ts index 64051dff93f..3464809dfc4 100644 --- a/acvm-repo/acvm_js/test/shared/nested_acir_call.ts +++ b/acvm-repo/acvm_js/test/shared/nested_acir_call.ts @@ -2,13 +2,13 @@ import { WitnessMap, StackItem, WitnessStack } from '@noir-lang/acvm_js'; // See `nested_acir_call_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 205, 146, 97, 10, 195, 32, 12, 133, 163, 66, 207, 147, 24, 173, 241, 223, 174, 50, - 153, 189, 255, 17, 214, 177, 148, 57, 17, 250, 99, 14, 250, 224, 97, 144, 16, 146, 143, 231, 224, 45, 167, 126, 105, - 217, 109, 118, 91, 248, 200, 168, 225, 248, 63, 107, 114, 208, 233, 104, 188, 233, 139, 191, 137, 108, 51, 139, 113, - 13, 161, 38, 95, 137, 233, 142, 62, 23, 137, 24, 98, 89, 133, 132, 162, 196, 135, 23, 230, 42, 65, 82, 46, 57, 97, - 166, 192, 149, 182, 152, 121, 211, 97, 110, 222, 94, 8, 13, 132, 182, 54, 48, 144, 235, 8, 254, 11, 22, 76, 132, 101, - 231, 237, 229, 23, 189, 213, 54, 119, 15, 83, 212, 199, 172, 175, 191, 226, 102, 96, 140, 251, 202, 84, 13, 204, 141, - 224, 25, 176, 161, 158, 53, 121, 144, 73, 14, 4, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 146, 81, 10, 195, 48, 8, 134, 77, 164, 247, 209, 152, 52, 230, 109, 87, 89, + 88, 122, 255, 35, 172, 99, 41, 11, 89, 161, 15, 77, 31, 250, 193, 143, 34, 34, 250, 35, 194, 23, 172, 250, 48, 173, + 50, 171, 44, 252, 48, 85, 176, 213, 143, 154, 16, 58, 182, 198, 71, 141, 116, 14, 182, 205, 44, 161, 217, 251, 18, 93, + 97, 225, 39, 185, 148, 53, 144, 15, 121, 86, 86, 14, 26, 94, 78, 69, 138, 122, 141, 41, 167, 72, 137, 189, 20, 94, 66, + 146, 165, 14, 195, 113, 123, 17, 52, 38, 180, 185, 129, 127, 176, 51, 240, 42, 175, 96, 160, 87, 118, 220, 94, 110, + 170, 183, 218, 230, 238, 221, 39, 234, 191, 172, 207, 177, 171, 153, 155, 153, 106, 96, 236, 3, 30, 249, 181, 199, 27, + 99, 149, 130, 253, 11, 4, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ diff --git a/acvm-repo/acvm_js/test/shared/schnorr_verify.ts b/acvm-repo/acvm_js/test/shared/schnorr_verify.ts deleted file mode 100644 index 830ca1026d6..00000000000 --- a/acvm-repo/acvm_js/test/shared/schnorr_verify.ts +++ /dev/null @@ -1,101 +0,0 @@ -// See `schnorr_verify_circuit` integration test in `acir/tests/test_program_serialization.rs`. -export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 85, 211, 103, 78, 2, 81, 24, 70, 225, 193, 130, 96, 239, 189, 96, 239, 189, 35, 34, - 34, 34, 34, 238, 130, 253, 47, 129, 192, 9, 223, 36, 7, 146, 201, 60, 209, 31, 144, 123, 207, 155, 73, 250, 159, 118, - 239, 201, 132, 121, 103, 227, 205, 211, 137, 247, 144, 60, 220, 123, 114, 225, 17, 121, 84, 206, 202, 99, 114, 78, - 206, 203, 227, 242, 132, 60, 41, 79, 201, 211, 242, 140, 60, 43, 207, 201, 243, 242, 130, 188, 40, 47, 201, 203, 242, - 138, 188, 42, 175, 201, 235, 242, 134, 188, 41, 111, 201, 219, 242, 142, 92, 144, 119, 229, 61, 121, 95, 62, 144, 15, - 229, 35, 249, 88, 62, 145, 79, 229, 51, 249, 92, 190, 144, 47, 229, 43, 249, 90, 190, 145, 111, 229, 59, 249, 94, 126, - 144, 31, 229, 39, 249, 89, 126, 145, 95, 229, 162, 252, 38, 151, 228, 119, 185, 44, 127, 200, 21, 249, 83, 174, 134, - 233, 52, 137, 191, 125, 233, 255, 53, 249, 91, 174, 203, 63, 114, 67, 254, 149, 155, 242, 159, 220, 10, 255, 199, 247, - 183, 244, 59, 216, 38, 155, 100, 139, 108, 144, 237, 165, 155, 203, 199, 111, 102, 83, 108, 137, 13, 177, 29, 54, 195, - 86, 216, 8, 219, 96, 19, 108, 129, 13, 208, 62, 205, 211, 58, 141, 211, 54, 77, 211, 50, 13, 211, 46, 205, 22, 146, - 126, 163, 180, 73, 147, 180, 72, 131, 180, 71, 115, 180, 70, 99, 180, 69, 83, 180, 68, 67, 180, 67, 51, 180, 66, 35, - 180, 65, 19, 180, 64, 3, 220, 61, 119, 206, 93, 115, 199, 197, 184, 211, 82, 220, 97, 57, 238, 172, 18, 119, 84, 141, - 187, 168, 197, 217, 215, 227, 172, 27, 113, 182, 205, 56, 203, 244, 204, 210, 115, 75, 116, 158, 3, 159, 46, 43, 32, - 188, 53, 25, 5, 0, 0, -]); - -export const initialWitnessMap = new Map([ - [1, '0x04b260954662e97f00cab9adb773a259097f7a274b83b113532bce27fa3fb96a'], - [2, '0x2fd51571db6c08666b0edfbfbc57d432068bccd0110a39b166ab243da0037197'], - [3, '0x000000000000000000000000000000000000000000000000000000000000002e'], - [4, '0x00000000000000000000000000000000000000000000000000000000000000ce'], - [5, '0x0000000000000000000000000000000000000000000000000000000000000052'], - [6, '0x00000000000000000000000000000000000000000000000000000000000000aa'], - [7, '0x0000000000000000000000000000000000000000000000000000000000000087'], - [8, '0x000000000000000000000000000000000000000000000000000000000000002a'], - [9, '0x0000000000000000000000000000000000000000000000000000000000000049'], - [10, '0x000000000000000000000000000000000000000000000000000000000000009d'], - [11, '0x0000000000000000000000000000000000000000000000000000000000000050'], - [12, '0x000000000000000000000000000000000000000000000000000000000000007c'], - [13, '0x000000000000000000000000000000000000000000000000000000000000009a'], - [14, '0x00000000000000000000000000000000000000000000000000000000000000aa'], - [15, '0x00000000000000000000000000000000000000000000000000000000000000df'], - [16, '0x0000000000000000000000000000000000000000000000000000000000000023'], - [17, '0x0000000000000000000000000000000000000000000000000000000000000034'], - [18, '0x0000000000000000000000000000000000000000000000000000000000000010'], - [19, '0x000000000000000000000000000000000000000000000000000000000000008a'], - [20, '0x0000000000000000000000000000000000000000000000000000000000000047'], - [21, '0x0000000000000000000000000000000000000000000000000000000000000063'], - [22, '0x00000000000000000000000000000000000000000000000000000000000000e8'], - [23, '0x0000000000000000000000000000000000000000000000000000000000000037'], - [24, '0x0000000000000000000000000000000000000000000000000000000000000054'], - [25, '0x0000000000000000000000000000000000000000000000000000000000000096'], - [26, '0x000000000000000000000000000000000000000000000000000000000000003e'], - [27, '0x00000000000000000000000000000000000000000000000000000000000000d5'], - [28, '0x00000000000000000000000000000000000000000000000000000000000000ae'], - [29, '0x0000000000000000000000000000000000000000000000000000000000000024'], - [30, '0x000000000000000000000000000000000000000000000000000000000000002d'], - [31, '0x0000000000000000000000000000000000000000000000000000000000000020'], - [32, '0x0000000000000000000000000000000000000000000000000000000000000080'], - [33, '0x000000000000000000000000000000000000000000000000000000000000004d'], - [34, '0x0000000000000000000000000000000000000000000000000000000000000047'], - [35, '0x00000000000000000000000000000000000000000000000000000000000000a5'], - [36, '0x00000000000000000000000000000000000000000000000000000000000000bb'], - [37, '0x00000000000000000000000000000000000000000000000000000000000000f6'], - [38, '0x00000000000000000000000000000000000000000000000000000000000000c3'], - [39, '0x000000000000000000000000000000000000000000000000000000000000000b'], - [40, '0x000000000000000000000000000000000000000000000000000000000000003b'], - [41, '0x0000000000000000000000000000000000000000000000000000000000000065'], - [42, '0x00000000000000000000000000000000000000000000000000000000000000c9'], - [43, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [44, '0x0000000000000000000000000000000000000000000000000000000000000085'], - [45, '0x0000000000000000000000000000000000000000000000000000000000000006'], - [46, '0x000000000000000000000000000000000000000000000000000000000000009e'], - [47, '0x000000000000000000000000000000000000000000000000000000000000002f'], - [48, '0x0000000000000000000000000000000000000000000000000000000000000010'], - [49, '0x00000000000000000000000000000000000000000000000000000000000000e6'], - [50, '0x0000000000000000000000000000000000000000000000000000000000000030'], - [51, '0x000000000000000000000000000000000000000000000000000000000000004a'], - [52, '0x0000000000000000000000000000000000000000000000000000000000000018'], - [53, '0x000000000000000000000000000000000000000000000000000000000000007c'], - [54, '0x00000000000000000000000000000000000000000000000000000000000000d0'], - [55, '0x00000000000000000000000000000000000000000000000000000000000000ab'], - [56, '0x0000000000000000000000000000000000000000000000000000000000000031'], - [57, '0x00000000000000000000000000000000000000000000000000000000000000d5'], - [58, '0x0000000000000000000000000000000000000000000000000000000000000063'], - [59, '0x0000000000000000000000000000000000000000000000000000000000000084'], - [60, '0x00000000000000000000000000000000000000000000000000000000000000a3'], - [61, '0x00000000000000000000000000000000000000000000000000000000000000a6'], - [62, '0x00000000000000000000000000000000000000000000000000000000000000d5'], - [63, '0x0000000000000000000000000000000000000000000000000000000000000091'], - [64, '0x000000000000000000000000000000000000000000000000000000000000000d'], - [65, '0x000000000000000000000000000000000000000000000000000000000000009c'], - [66, '0x00000000000000000000000000000000000000000000000000000000000000f9'], - [67, '0x0000000000000000000000000000000000000000000000000000000000000000'], - [68, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [69, '0x0000000000000000000000000000000000000000000000000000000000000002'], - [70, '0x0000000000000000000000000000000000000000000000000000000000000003'], - [71, '0x0000000000000000000000000000000000000000000000000000000000000004'], - [72, '0x0000000000000000000000000000000000000000000000000000000000000005'], - [73, '0x0000000000000000000000000000000000000000000000000000000000000006'], - [74, '0x0000000000000000000000000000000000000000000000000000000000000007'], - [75, '0x0000000000000000000000000000000000000000000000000000000000000008'], - [76, '0x0000000000000000000000000000000000000000000000000000000000000009'], -]); - -export const expectedWitnessMap = new Map(initialWitnessMap).set( - 77, - '0x0000000000000000000000000000000000000000000000000000000000000001', -); diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index b8b17db433c..fe3a938c503 100644 --- a/acvm-repo/blackbox_solver/Cargo.toml +++ b/acvm-repo/blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_blackbox_solver" description = "A solver for the blackbox functions found in ACIR and Brillig" # x-release-please-start-version -version = "0.50.0" +version = "1.0.0-beta.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -22,8 +22,7 @@ num-bigint = "0.4" blake2 = "0.10.6" blake3 = "1.5.0" -sha2 = { version="0.10.6", features = ["compress",] } -sha3 = "0.10.6" +sha2.workspace = true keccak = "0.1.4" k256 = { version = "0.11.0", features = [ "ecdsa", diff --git a/acvm-repo/blackbox_solver/src/bigint.rs b/acvm-repo/blackbox_solver/src/bigint.rs index b8bc9dc0d70..540862843ab 100644 --- a/acvm-repo/blackbox_solver/src/bigint.rs +++ b/acvm-repo/blackbox_solver/src/bigint.rs @@ -97,3 +97,51 @@ impl BigIntSolver { Ok(()) } } + +/// Wrapper over the generic bigint solver to automatically assign bigint IDs. +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct BigIntSolverWithId { + solver: BigIntSolver, + last_id: u32, +} + +impl BigIntSolverWithId { + pub fn create_bigint_id(&mut self) -> u32 { + let output = self.last_id; + self.last_id += 1; + output + } + + pub fn bigint_from_bytes( + &mut self, + inputs: &[u8], + modulus: &[u8], + ) -> Result { + let id = self.create_bigint_id(); + self.solver.bigint_from_bytes(inputs, modulus, id)?; + Ok(id) + } + + pub fn bigint_to_bytes(&self, input: u32) -> Result, BlackBoxResolutionError> { + self.solver.bigint_to_bytes(input) + } + + pub fn bigint_op( + &mut self, + lhs: u32, + rhs: u32, + func: BlackBoxFunc, + ) -> Result { + let modulus_lhs = self.solver.get_modulus(lhs, func)?; + let modulus_rhs = self.solver.get_modulus(rhs, func)?; + if modulus_lhs != modulus_rhs { + return Err(BlackBoxResolutionError::Failed( + func, + "moduli should be identical in BigInt operation".to_string(), + )); + } + let id = self.create_bigint_id(); + self.solver.bigint_op(lhs, rhs, id, func)?; + Ok(id) + } +} diff --git a/acvm-repo/blackbox_solver/src/curve_specific_solver.rs b/acvm-repo/blackbox_solver/src/curve_specific_solver.rs index f729a5033fb..b8fc3f47033 100644 --- a/acvm-repo/blackbox_solver/src/curve_specific_solver.rs +++ b/acvm-repo/blackbox_solver/src/curve_specific_solver.rs @@ -7,23 +7,6 @@ use crate::BlackBoxResolutionError; /// /// Returns an [`BlackBoxResolutionError`] if the backend does not support the given [`acir::BlackBoxFunc`]. pub trait BlackBoxFunctionSolver { - fn schnorr_verify( - &self, - public_key_x: &F, - public_key_y: &F, - signature: &[u8; 64], - message: &[u8], - ) -> Result; - fn pedersen_commitment( - &self, - inputs: &[F], - domain_separator: u32, - ) -> Result<(F, F), BlackBoxResolutionError>; - fn pedersen_hash( - &self, - inputs: &[F], - domain_separator: u32, - ) -> Result; fn multi_scalar_mul( &self, points: &[F], @@ -58,30 +41,6 @@ impl StubbedBlackBoxSolver { } impl BlackBoxFunctionSolver for StubbedBlackBoxSolver { - fn schnorr_verify( - &self, - _public_key_x: &F, - _public_key_y: &F, - _signature: &[u8; 64], - _message: &[u8], - ) -> Result { - Err(Self::fail(BlackBoxFunc::SchnorrVerify)) - } - fn pedersen_commitment( - &self, - _inputs: &[F], - _domain_separator: u32, - ) -> Result<(F, F), BlackBoxResolutionError> { - Err(Self::fail(BlackBoxFunc::PedersenCommitment)) - } - fn pedersen_hash( - &self, - _inputs: &[F], - _domain_separator: u32, - ) -> Result { - Err(Self::fail(BlackBoxFunc::PedersenHash)) - } - fn multi_scalar_mul( &self, _points: &[F], diff --git a/acvm-repo/blackbox_solver/src/hash.rs b/acvm-repo/blackbox_solver/src/hash.rs index af503117466..660a1fb0e5d 100644 --- a/acvm-repo/blackbox_solver/src/hash.rs +++ b/acvm-repo/blackbox_solver/src/hash.rs @@ -1,7 +1,6 @@ use acir::BlackBoxFunc; use blake2::digest::generic_array::GenericArray; use blake2::{Blake2s256, Digest}; -use sha3::Keccak256; use crate::BlackBoxResolutionError; @@ -22,11 +21,6 @@ pub fn blake3(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { Ok(blake3::hash(inputs).into()) } -pub fn keccak256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { - generic_hash_256::(inputs) - .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Keccak256, err)) -} - pub fn sha256_compression(state: &mut [u32; 8], msg_blocks: &[u32; 16]) { let mut blocks = [0_u8; 64]; for (i, block) in msg_blocks.iter().enumerate() { diff --git a/acvm-repo/blackbox_solver/src/lib.rs b/acvm-repo/blackbox_solver/src/lib.rs index 87ca539f435..0fa56c2f531 100644 --- a/acvm-repo/blackbox_solver/src/lib.rs +++ b/acvm-repo/blackbox_solver/src/lib.rs @@ -5,7 +5,7 @@ //! This crate provides the implementation of BlackBox functions of ACIR and Brillig. //! For functions that are backend-dependent, it provides a Trait [BlackBoxFunctionSolver] that must be implemented by the backend. -//! For functions that have a reference implementation, such as [keccak256], this crate exports the reference implementation directly. +//! For functions that have a reference implementation, such as [keccakf1600], this crate exports the reference implementation directly. use acir::BlackBoxFunc; use thiserror::Error; @@ -18,10 +18,10 @@ mod hash; mod logic; pub use aes128::aes128_encrypt; -pub use bigint::BigIntSolver; +pub use bigint::{BigIntSolver, BigIntSolverWithId}; pub use curve_specific_solver::{BlackBoxFunctionSolver, StubbedBlackBoxSolver}; pub use ecdsa::{ecdsa_secp256k1_verify, ecdsa_secp256r1_verify}; -pub use hash::{blake2s, blake3, keccak256, keccakf1600, sha256_compression}; +pub use hash::{blake2s, blake3, keccakf1600, sha256_compression}; pub use logic::{bit_and, bit_xor}; #[derive(Clone, PartialEq, Eq, Debug, Error)] diff --git a/acvm-repo/bn254_blackbox_solver/Cargo.toml b/acvm-repo/bn254_blackbox_solver/Cargo.toml index c892dc45fdd..825a0ef0481 100644 --- a/acvm-repo/bn254_blackbox_solver/Cargo.toml +++ b/acvm-repo/bn254_blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "bn254_blackbox_solver" description = "Solvers for black box functions which are specific for the bn254 curve" # x-release-please-start-version -version = "0.50.0" +version = "1.0.0-beta.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -19,10 +19,10 @@ workspace = true acir.workspace = true acvm_blackbox_solver.workspace = true hex.workspace = true -lazy_static = "1.4" +lazy_static.workspace = true ark-bn254.workspace = true -grumpkin.workspace = true +grumpkin.workspace = true ark-ec.workspace = true ark-ff.workspace = true num-bigint.workspace = true @@ -30,7 +30,7 @@ num-bigint.workspace = true [dev-dependencies] ark-std.workspace = true criterion = "0.5.0" -pprof = { version = "0.12", features = [ +pprof = { version = "0.14", features = [ "flamegraph", "frame-pointer", "criterion", diff --git a/acvm-repo/bn254_blackbox_solver/benches/criterion.rs b/acvm-repo/bn254_blackbox_solver/benches/criterion.rs index e7917fa1adc..fc566b70a26 100644 --- a/acvm-repo/bn254_blackbox_solver/benches/criterion.rs +++ b/acvm-repo/bn254_blackbox_solver/benches/criterion.rs @@ -2,8 +2,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use std::{hint::black_box, time::Duration}; use acir::{AcirField, FieldElement}; -use acvm_blackbox_solver::BlackBoxFunctionSolver; -use bn254_blackbox_solver::{poseidon2_permutation, Bn254BlackBoxSolver}; +use bn254_blackbox_solver::poseidon2_permutation; use pprof::criterion::{Output, PProfProfiler}; @@ -13,40 +12,10 @@ fn bench_poseidon2(c: &mut Criterion) { c.bench_function("poseidon2", |b| b.iter(|| poseidon2_permutation(black_box(&inputs), 4))); } -fn bench_schnorr_verify(c: &mut Criterion) { - let pub_key_x = FieldElement::from_hex( - "0x04b260954662e97f00cab9adb773a259097f7a274b83b113532bce27fa3fb96a", - ) - .unwrap(); - let pub_key_y = FieldElement::from_hex( - "0x2fd51571db6c08666b0edfbfbc57d432068bccd0110a39b166ab243da0037197", - ) - .unwrap(); - let sig_bytes: [u8; 64] = [ - 1, 13, 119, 112, 212, 39, 233, 41, 84, 235, 255, 93, 245, 172, 186, 83, 157, 253, 76, 77, - 33, 128, 178, 15, 214, 67, 105, 107, 177, 234, 77, 48, 27, 237, 155, 84, 39, 84, 247, 27, - 22, 8, 176, 230, 24, 115, 145, 220, 254, 122, 135, 179, 171, 4, 214, 202, 64, 199, 19, 84, - 239, 138, 124, 12, - ]; - - let message: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - - c.bench_function("schnorr_verify", |b| { - b.iter(|| { - Bn254BlackBoxSolver.schnorr_verify( - black_box(&pub_key_x), - black_box(&pub_key_y), - black_box(&sig_bytes), - black_box(message), - ) - }) - }); -} - criterion_group!( name = benches; config = Criterion::default().sample_size(40).measurement_time(Duration::from_secs(20)).with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); - targets = bench_poseidon2, bench_schnorr_verify + targets = bench_poseidon2 ); criterion_main!(benches); diff --git a/acvm-repo/bn254_blackbox_solver/src/embedded_curve_ops.rs b/acvm-repo/bn254_blackbox_solver/src/embedded_curve_ops.rs index 35cc68051d7..e599fd25593 100644 --- a/acvm-repo/bn254_blackbox_solver/src/embedded_curve_ops.rs +++ b/acvm-repo/bn254_blackbox_solver/src/embedded_curve_ops.rs @@ -1,6 +1,5 @@ // TODO(https://github.com/noir-lang/noir/issues/4932): rename this file to something more generic use ark_ec::AffineRepr; -use ark_ff::MontConfig; use num_bigint::BigUint; use crate::FieldElement; @@ -16,7 +15,6 @@ pub fn multi_scalar_mul( scalars_hi: &[FieldElement], ) -> Result<(FieldElement, FieldElement, FieldElement), BlackBoxResolutionError> { if points.len() != 3 * scalars_lo.len() || scalars_lo.len() != scalars_hi.len() { - dbg!(&points.len(), &scalars_lo.len(), &scalars_hi.len()); return Err(BlackBoxResolutionError::Failed( BlackBoxFunc::MultiScalarMul, "Points and scalars must have the same length".to_string(), @@ -47,15 +45,15 @@ pub fn multi_scalar_mul( let mut bytes = scalar_high.to_be_bytes().to_vec(); bytes.extend_from_slice(&scalar_low.to_be_bytes()); - // Check if this is smaller than the grumpkin modulus let grumpkin_integer = BigUint::from_bytes_be(&bytes); - if grumpkin_integer >= grumpkin::FrConfig::MODULUS.into() { - return Err(BlackBoxResolutionError::Failed( - BlackBoxFunc::MultiScalarMul, - format!("{} is not a valid grumpkin scalar", grumpkin_integer.to_str_radix(16)), - )); - } + // Check if this is smaller than the grumpkin modulus + // if grumpkin_integer >= grumpkin::FrConfig::MODULUS.into() { + // return Err(BlackBoxResolutionError::Failed( + // BlackBoxFunc::MultiScalarMul, + // format!("{} is not a valid grumpkin scalar", grumpkin_integer.to_str_radix(16)), + // )); + // } let iteration_output_point = grumpkin::SWAffine::from(point.mul_bigint(grumpkin_integer.to_u64_digits())); @@ -121,8 +119,6 @@ fn create_point( mod tests { use super::*; - use ark_ff::BigInteger; - fn get_generator() -> [FieldElement; 3] { let generator = grumpkin::SWAffine::generator(); let generator_x = FieldElement::from_repr(*generator.x().unwrap()); @@ -176,23 +172,23 @@ mod tests { assert_eq!(res, expected_error); } - #[test] - fn rejects_grumpkin_modulus() { - let x = grumpkin::FrConfig::MODULUS.to_bytes_be(); + // #[test] + // fn rejects_grumpkin_modulus() { + // let x = grumpkin::FrConfig::MODULUS.to_bytes_be(); - let low = FieldElement::from_be_bytes_reduce(&x[16..32]); - let high = FieldElement::from_be_bytes_reduce(&x[0..16]); + // let low = FieldElement::from_be_bytes_reduce(&x[16..32]); + // let high = FieldElement::from_be_bytes_reduce(&x[0..16]); - let res = multi_scalar_mul(&get_generator(), &[low], &[high]); + // let res = multi_scalar_mul(&get_generator(), &[low], &[high]); - assert_eq!( - res, - Err(BlackBoxResolutionError::Failed( - BlackBoxFunc::MultiScalarMul, - "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 is not a valid grumpkin scalar".into(), - )) - ); - } + // assert_eq!( + // res, + // Err(BlackBoxResolutionError::Failed( + // BlackBoxFunc::MultiScalarMul, + // "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 is not a valid grumpkin scalar".into(), + // )) + // ); + // } #[test] fn rejects_invalid_point() { diff --git a/acvm-repo/bn254_blackbox_solver/src/lib.rs b/acvm-repo/bn254_blackbox_solver/src/lib.rs index 952c4498d84..f738a375ab1 100644 --- a/acvm-repo/bn254_blackbox_solver/src/lib.rs +++ b/acvm-repo/bn254_blackbox_solver/src/lib.rs @@ -6,11 +6,8 @@ use acvm_blackbox_solver::{BlackBoxFunctionSolver, BlackBoxResolutionError}; mod embedded_curve_ops; mod generator; -mod pedersen; mod poseidon2; -mod schnorr; -use ark_ec::AffineRepr; pub use embedded_curve_ops::{embedded_curve_add, multi_scalar_mul}; pub use generator::generators::derive_generators; pub use poseidon2::{ @@ -26,51 +23,6 @@ type FieldElement = acir::acir_field::GenericFieldElement; pub struct Bn254BlackBoxSolver; impl BlackBoxFunctionSolver for Bn254BlackBoxSolver { - fn schnorr_verify( - &self, - public_key_x: &FieldElement, - public_key_y: &FieldElement, - signature: &[u8; 64], - message: &[u8], - ) -> Result { - let sig_s: [u8; 32] = signature[0..32].try_into().unwrap(); - let sig_e: [u8; 32] = signature[32..64].try_into().unwrap(); - Ok(schnorr::verify_signature( - public_key_x.into_repr(), - public_key_y.into_repr(), - sig_s, - sig_e, - message, - )) - } - - fn pedersen_commitment( - &self, - inputs: &[FieldElement], - domain_separator: u32, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - let inputs: Vec = inputs.iter().map(|input| input.into_repr()).collect(); - let result = pedersen::commitment::commit_native_with_index(&inputs, domain_separator); - let result = if let Some((x, y)) = result.xy() { - (FieldElement::from_repr(*x), FieldElement::from_repr(*y)) - } else { - (FieldElement::from(0_u128), FieldElement::from(0_u128)) - }; - - Ok(result) - } - - fn pedersen_hash( - &self, - inputs: &[FieldElement], - domain_separator: u32, - ) -> Result { - let inputs: Vec = inputs.iter().map(|input| input.into_repr()).collect(); - let result = pedersen::hash::hash_with_index(&inputs, domain_separator); - let result = FieldElement::from_repr(result); - Ok(result) - } - fn multi_scalar_mul( &self, points: &[FieldElement], diff --git a/acvm-repo/bn254_blackbox_solver/src/pedersen/commitment.rs b/acvm-repo/bn254_blackbox_solver/src/pedersen/commitment.rs deleted file mode 100644 index 03f03fcf5ab..00000000000 --- a/acvm-repo/bn254_blackbox_solver/src/pedersen/commitment.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Taken from: https://github.com/laudiacay/barustenberg/blob/df6bc6f095fe7f288bf6a12e7317fd8eb33d68ae/barustenberg/src/crypto/pedersen/pederson.rs - -use ark_ec::{short_weierstrass::Affine, AffineRepr, CurveGroup}; -use ark_ff::{MontConfig, PrimeField}; -use grumpkin::{Fq, FqConfig, Fr, FrConfig, GrumpkinParameters}; - -use crate::generator::generators::{derive_generators, DEFAULT_DOMAIN_SEPARATOR}; - -/// Given a vector of fields, generate a pedersen commitment using the indexed generators. -pub(crate) fn commit_native_with_index( - inputs: &[Fq], - starting_index: u32, -) -> Affine { - let generators = - derive_generators(DEFAULT_DOMAIN_SEPARATOR, inputs.len() as u32, starting_index); - - // As |F_r| > |F_q|, we can safely convert any `F_q` into an `F_r` uniquely. - assert!(FrConfig::MODULUS > FqConfig::MODULUS); - - inputs.iter().enumerate().fold(Affine::zero(), |mut acc, (i, input)| { - acc = (acc + (generators[i] * Fr::from_bigint(input.into_bigint()).unwrap()).into_affine()) - .into_affine(); - acc - }) -} - -#[cfg(test)] -mod test { - - use acir::AcirField; - use ark_ec::short_weierstrass::Affine; - use ark_std::{One, Zero}; - use grumpkin::Fq; - - use crate::pedersen::commitment::commit_native_with_index; - use crate::FieldElement; - - #[test] - fn commitment() { - // https://github.com/AztecProtocol/aztec-packages/blob/72931bdb8202c34042cdfb8cee2ef44b75939879/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/pedersen.test.cpp#L10-L18 - let res = commit_native_with_index(&[Fq::one(), Fq::one()], 0); - let expected = Affine::new( - FieldElement::from_hex( - "0x2f7a8f9a6c96926682205fb73ee43215bf13523c19d7afe36f12760266cdfe15", - ) - .unwrap() - .into_repr(), - FieldElement::from_hex( - "0x01916b316adbbf0e10e39b18c1d24b33ec84b46daddf72f43878bcc92b6057e6", - ) - .unwrap() - .into_repr(), - ); - - assert_eq!(res, expected); - } - - #[test] - fn commitment_with_zero() { - // https://github.com/AztecProtocol/aztec-packages/blob/72931bdb8202c34042cdfb8cee2ef44b75939879/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/pedersen.test.cpp#L20-L29 - let res = commit_native_with_index(&[Fq::zero(), Fq::one()], 0); - let expected = Affine::new( - FieldElement::from_hex( - "0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402", - ) - .unwrap() - .into_repr(), - FieldElement::from_hex( - "0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126", - ) - .unwrap() - .into_repr(), - ); - - assert_eq!(res, expected); - } -} diff --git a/acvm-repo/bn254_blackbox_solver/src/pedersen/hash.rs b/acvm-repo/bn254_blackbox_solver/src/pedersen/hash.rs deleted file mode 100644 index 152526a9943..00000000000 --- a/acvm-repo/bn254_blackbox_solver/src/pedersen/hash.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Taken from: https://github.com/laudiacay/barustenberg/blob/df6bc6f095fe7f288bf6a12e7317fd8eb33d68ae/barustenberg/src/crypto/pedersen/pederson_hash.rs - -use std::sync::OnceLock; - -use ark_ec::{short_weierstrass::Affine, CurveConfig, CurveGroup}; -use grumpkin::GrumpkinParameters; - -use crate::generator::generators::derive_generators; - -use super::commitment::commit_native_with_index; - -/// Given a vector of fields, generate a pedersen hash using the indexed generators. -pub(crate) fn hash_with_index( - inputs: &[grumpkin::Fq], - starting_index: u32, -) -> ::BaseField { - let length_as_scalar: ::ScalarField = - (inputs.len() as u64).into(); - let length_prefix = *length_generator() * length_as_scalar; - let result = length_prefix + commit_native_with_index(inputs, starting_index); - result.into_affine().x -} - -fn length_generator() -> &'static Affine { - static INSTANCE: OnceLock> = OnceLock::new(); - INSTANCE.get_or_init(|| derive_generators("pedersen_hash_length".as_bytes(), 1, 0)[0]) -} - -#[cfg(test)] -pub(crate) mod test { - - use super::*; - use crate::FieldElement; - - use acir::AcirField; - use ark_std::One; - use grumpkin::Fq; - - //reference: https://github.com/AztecProtocol/barretenberg/blob/master/cpp/src/barretenberg/crypto/pedersen_hash/pedersen.test.cpp - #[test] - fn hash_one() { - // https://github.com/AztecProtocol/aztec-packages/blob/72931bdb8202c34042cdfb8cee2ef44b75939879/barretenberg/cpp/src/barretenberg/crypto/pedersen_hash/pedersen.test.cpp#L21-L26 - let res = hash_with_index(&[Fq::one(), Fq::one()], 0); - - assert_eq!( - res, - FieldElement::from_hex( - "0x07ebfbf4df29888c6cd6dca13d4bb9d1a923013ddbbcbdc3378ab8845463297b", - ) - .unwrap() - .into_repr(), - ); - } - - #[test] - fn test_hash_with_index() { - // https://github.com/AztecProtocol/aztec-packages/blob/72931bdb8202c34042cdfb8cee2ef44b75939879/barretenberg/cpp/src/barretenberg/crypto/pedersen_hash/pedersen.test.cpp#L28-L33 - let res = hash_with_index(&[Fq::one(), Fq::one()], 5); - - assert_eq!( - res, - FieldElement::from_hex( - "0x1c446df60816b897cda124524e6b03f36df0cec333fad87617aab70d7861daa6", - ) - .unwrap() - .into_repr(), - ); - } -} diff --git a/acvm-repo/bn254_blackbox_solver/src/pedersen/mod.rs b/acvm-repo/bn254_blackbox_solver/src/pedersen/mod.rs deleted file mode 100644 index c3c4ed56450..00000000000 --- a/acvm-repo/bn254_blackbox_solver/src/pedersen/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub(crate) mod commitment; -pub(crate) mod hash; diff --git a/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs b/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs index 64823e37029..3aa735388ca 100644 --- a/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs +++ b/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs @@ -544,13 +544,23 @@ impl<'a> Poseidon2<'a> { } /// Performs a poseidon hash with a sponge construction equivalent to the one in poseidon2.nr -pub fn poseidon_hash(inputs: &[FieldElement]) -> Result { +/// +/// The `is_variable_length` parameter is there to so we can produce an equivalent hash with +/// the Barretenberg implementation which distinguishes between variable and fixed length inputs. +/// Set it to true if the input length matches the static size expected by the Noir function. +pub fn poseidon_hash( + inputs: &[FieldElement], + is_variable_length: bool, +) -> Result { let two_pow_64 = 18446744073709551616_u128.into(); let iv = FieldElement::from(inputs.len()) * two_pow_64; let mut sponge = Poseidon2Sponge::new(iv, 3); for input in inputs.iter() { sponge.absorb(*input)?; } + if is_variable_length { + sponge.absorb(FieldElement::from(1u32))?; + } sponge.squeeze() } @@ -640,7 +650,7 @@ mod test { FieldElement::from(3u128), FieldElement::from(4u128), ]; - let result = super::poseidon_hash(&fields).expect("should hash successfully"); + let result = super::poseidon_hash(&fields, false).expect("should hash successfully"); assert_eq!( result, field_from_hex("130bf204a32cac1f0ace56c78b731aa3809f06df2731ebcf6b3464a15788b1b9"), diff --git a/acvm-repo/bn254_blackbox_solver/src/schnorr/mod.rs b/acvm-repo/bn254_blackbox_solver/src/schnorr/mod.rs deleted file mode 100644 index 8e3a40803f8..00000000000 --- a/acvm-repo/bn254_blackbox_solver/src/schnorr/mod.rs +++ /dev/null @@ -1,147 +0,0 @@ -use acvm_blackbox_solver::blake2s; -use ark_ec::{ - short_weierstrass::{Affine, SWCurveConfig}, - AffineRepr, CurveConfig, CurveGroup, -}; -use ark_ff::{BigInteger, PrimeField, Zero}; -use grumpkin::{Fq, GrumpkinParameters}; - -pub(crate) fn verify_signature( - pub_key_x: Fq, - pub_key_y: Fq, - sig_s_bytes: [u8; 32], - sig_e_bytes: [u8; 32], - message: &[u8], -) -> bool { - let pub_key = Affine::::new_unchecked(pub_key_x, pub_key_y); - - if !pub_key.is_on_curve() - || !pub_key.is_in_correct_subgroup_assuming_on_curve() - || pub_key.is_zero() - { - return false; - } - - let sig_s = - ::ScalarField::from_be_bytes_mod_order(&sig_s_bytes); - let sig_e = - ::ScalarField::from_be_bytes_mod_order(&sig_e_bytes); - - if sig_s.is_zero() || sig_e.is_zero() { - return false; - } - - // R = g^{sig.s} • pub^{sig.e} - let r = GrumpkinParameters::GENERATOR * sig_s + pub_key * sig_e; - if r.is_zero() { - // this result implies k == 0, which would be catastrophic for the prover. - // it is a cheap check that ensures this doesn't happen. - return false; - } - - // compare the _hashes_ rather than field elements modulo r - // e = H(pedersen(r, pk.x, pk.y), m), where r = R.x - let target_e_bytes = schnorr_generate_challenge(message, pub_key_x, pub_key_y, r.into_affine()); - - sig_e_bytes == target_e_bytes -} - -fn schnorr_generate_challenge( - message: &[u8], - pub_key_x: Fq, - pub_key_y: Fq, - r: Affine, -) -> [u8; 32] { - // create challenge message pedersen_commitment(R.x, pubkey) - - let r_x = *r.x().expect("r has been checked to be non-zero"); - let pedersen_hash = crate::pedersen::hash::hash_with_index(&[r_x, pub_key_x, pub_key_y], 0); - - let mut hash_input: Vec = pedersen_hash.into_bigint().to_bytes_be(); - hash_input.extend(message); - - blake2s(&hash_input).unwrap() -} - -#[cfg(test)] -mod schnorr_tests { - use acir::AcirField; - - use super::verify_signature; - use crate::FieldElement; - - #[test] - fn verifies_valid_signature() { - let pub_key_x: grumpkin::Fq = FieldElement::from_hex( - "0x04b260954662e97f00cab9adb773a259097f7a274b83b113532bce27fa3fb96a", - ) - .unwrap() - .into_repr(); - let pub_key_y: grumpkin::Fq = FieldElement::from_hex( - "0x2fd51571db6c08666b0edfbfbc57d432068bccd0110a39b166ab243da0037197", - ) - .unwrap() - .into_repr(); - let sig_s_bytes: [u8; 32] = [ - 1, 13, 119, 112, 212, 39, 233, 41, 84, 235, 255, 93, 245, 172, 186, 83, 157, 253, 76, - 77, 33, 128, 178, 15, 214, 67, 105, 107, 177, 234, 77, 48, - ]; - let sig_e_bytes: [u8; 32] = [ - 27, 237, 155, 84, 39, 84, 247, 27, 22, 8, 176, 230, 24, 115, 145, 220, 254, 122, 135, - 179, 171, 4, 214, 202, 64, 199, 19, 84, 239, 138, 124, 12, - ]; - let message: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - - assert!(verify_signature(pub_key_x, pub_key_y, sig_s_bytes, sig_e_bytes, message)); - } - - #[test] - fn rejects_zero_e() { - let pub_key_x: grumpkin::Fq = FieldElement::from_hex( - "0x04b260954662e97f00cab9adb773a259097f7a274b83b113532bce27fa3fb96a", - ) - .unwrap() - .into_repr(); - let pub_key_y: grumpkin::Fq = FieldElement::from_hex( - "0x2fd51571db6c08666b0edfbfbc57d432068bccd0110a39b166ab243da0037197", - ) - .unwrap() - .into_repr(); - let sig_s_bytes: [u8; 32] = [ - 1, 13, 119, 112, 212, 39, 233, 41, 84, 235, 255, 93, 245, 172, 186, 83, 157, 253, 76, - 77, 33, 128, 178, 15, 214, 67, 105, 107, 177, 234, 77, 48, - ]; - let sig_e_bytes: [u8; 32] = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - ]; - let message: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - - assert!(!verify_signature(pub_key_x, pub_key_y, sig_s_bytes, sig_e_bytes, message)); - } - - #[test] - fn rejects_zero_s() { - let pub_key_x: grumpkin::Fq = FieldElement::from_hex( - "0x04b260954662e97f00cab9adb773a259097f7a274b83b113532bce27fa3fb96a", - ) - .unwrap() - .into_repr(); - let pub_key_y: grumpkin::Fq = FieldElement::from_hex( - "0x2fd51571db6c08666b0edfbfbc57d432068bccd0110a39b166ab243da0037197", - ) - .unwrap() - .into_repr(); - let sig_s_bytes: [u8; 32] = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - ]; - let sig_e_bytes: [u8; 32] = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - ]; - let message: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; - - assert!(!verify_signature(pub_key_x, pub_key_y, sig_s_bytes, sig_e_bytes, message)); - } -} diff --git a/acvm-repo/brillig/Cargo.toml b/acvm-repo/brillig/Cargo.toml index 0dec8fa2147..9cc724f2b11 100644 --- a/acvm-repo/brillig/Cargo.toml +++ b/acvm-repo/brillig/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig" description = "Brillig is the bytecode ACIR uses for non-determinism." # x-release-please-start-version -version = "0.50.0" +version = "1.0.0-beta.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/brillig/src/black_box.rs b/acvm-repo/brillig/src/black_box.rs index 534ef7d318e..f185b36e6c8 100644 --- a/acvm-repo/brillig/src/black_box.rs +++ b/acvm-repo/brillig/src/black_box.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; /// These opcodes provide an equivalent of ACIR blackbox functions. /// They are implemented as native functions in the VM. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)] pub enum BlackBoxOp { /// Encrypts a message using AES128. AES128Encrypt { @@ -22,14 +22,9 @@ pub enum BlackBoxOp { message: HeapVector, output: HeapArray, }, - /// Calculates the Keccak256 hash of the inputs. - Keccak256 { - message: HeapVector, - output: HeapArray, - }, /// Keccak Permutation function of 1600 width Keccakf1600 { - message: HeapVector, + input: HeapArray, output: HeapArray, }, /// Verifies a ECDSA signature over the secp256k1 curve. @@ -48,26 +43,7 @@ pub enum BlackBoxOp { signature: HeapArray, result: MemoryAddress, }, - /// Verifies a Schnorr signature over a curve which is "pairing friendly" with the curve on which the Brillig bytecode is defined. - SchnorrVerify { - public_key_x: MemoryAddress, - public_key_y: MemoryAddress, - message: HeapVector, - signature: HeapVector, - result: MemoryAddress, - }, - /// Will be deprecated - PedersenCommitment { - inputs: HeapVector, - domain_separator: MemoryAddress, - output: HeapArray, - }, - /// Will be deprecated - PedersenHash { - inputs: HeapVector, - domain_separator: MemoryAddress, - output: MemoryAddress, - }, + /// Performs multi scalar multiplication over the embedded curve. MultiScalarMul { points: HeapVector, @@ -119,8 +95,8 @@ pub enum BlackBoxOp { len: MemoryAddress, }, Sha256Compression { - input: HeapVector, - hash_values: HeapVector, + input: HeapArray, + hash_values: HeapArray, output: HeapArray, }, ToRadix { diff --git a/acvm-repo/brillig/src/lib.rs b/acvm-repo/brillig/src/lib.rs index 5bd9f898d59..cf31ff79996 100644 --- a/acvm-repo/brillig/src/lib.rs +++ b/acvm-repo/brillig/src/lib.rs @@ -4,7 +4,6 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] //! The Brillig bytecode is distinct from regular [ACIR][acir] in that it does not generate constraints. -//! This is a generalization over the fixed directives that exists within in the ACVM. //! //! [acir]: https://crates.io/crates/acir //! [acvm]: https://crates.io/crates/acvm diff --git a/acvm-repo/brillig/src/opcodes.rs b/acvm-repo/brillig/src/opcodes.rs index 45df2aca2d8..1cb31ca3d0a 100644 --- a/acvm-repo/brillig/src/opcodes.rs +++ b/acvm-repo/brillig/src/opcodes.rs @@ -5,23 +5,58 @@ use serde::{Deserialize, Serialize}; pub type Label = usize; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] -pub struct MemoryAddress(pub usize); +pub enum MemoryAddress { + Direct(usize), + Relative(usize), +} /// `MemoryAddress` refers to the index in VM memory. impl MemoryAddress { + pub fn direct(address: usize) -> Self { + MemoryAddress::Direct(address) + } + pub fn relative(offset: usize) -> Self { + MemoryAddress::Relative(offset) + } + + pub fn unwrap_direct(self) -> usize { + match self { + MemoryAddress::Direct(address) => address, + MemoryAddress::Relative(_) => panic!("Expected direct memory address"), + } + } + + pub fn unwrap_relative(self) -> usize { + match self { + MemoryAddress::Direct(_) => panic!("Expected relative memory address"), + MemoryAddress::Relative(offset) => offset, + } + } + pub fn to_usize(self) -> usize { - self.0 + match self { + MemoryAddress::Direct(address) => address, + MemoryAddress::Relative(offset) => offset, + } + } + + pub fn is_relative(&self) -> bool { + match self { + MemoryAddress::Relative(_) => true, + MemoryAddress::Direct(_) => false, + } } -} -impl From for MemoryAddress { - fn from(value: usize) -> Self { - MemoryAddress(value) + pub fn offset(&self, amount: usize) -> Self { + match self { + MemoryAddress::Direct(address) => MemoryAddress::Direct(address + amount), + MemoryAddress::Relative(offset) => MemoryAddress::Relative(offset + amount), + } } } /// Describes the memory layout for an array/vector element -#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Hash)] pub enum HeapValueType { // A single field element is enough to represent the value with a given bit size Simple(BitSize), @@ -46,7 +81,7 @@ impl HeapValueType { } /// A fixed-sized array starting from a Brillig memory location. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, Hash)] pub struct HeapArray { pub pointer: MemoryAddress, pub size: usize, @@ -54,20 +89,19 @@ pub struct HeapArray { impl Default for HeapArray { fn default() -> Self { - Self { pointer: MemoryAddress(0), size: 0 } + Self { pointer: MemoryAddress::direct(0), size: 0 } } } /// A memory-sized vector passed starting from a Brillig memory location and with a memory-held size -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, Hash)] pub struct HeapVector { pub pointer: MemoryAddress, pub size: MemoryAddress, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord, Hash)] pub enum IntegerBitSize { - U0, // Uninitialized U1, U8, U16, @@ -79,7 +113,6 @@ pub enum IntegerBitSize { impl From for u32 { fn from(bit_size: IntegerBitSize) -> u32 { match bit_size { - IntegerBitSize::U0 => 0, IntegerBitSize::U1 => 1, IntegerBitSize::U8 => 8, IntegerBitSize::U16 => 16, @@ -95,7 +128,6 @@ impl TryFrom for IntegerBitSize { fn try_from(value: u32) -> Result { match value { - 0 => Ok(IntegerBitSize::U0), 1 => Ok(IntegerBitSize::U1), 8 => Ok(IntegerBitSize::U8), 16 => Ok(IntegerBitSize::U16), @@ -110,7 +142,6 @@ impl TryFrom for IntegerBitSize { impl std::fmt::Display for IntegerBitSize { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - IntegerBitSize::U0 => write!(f, "null"), IntegerBitSize::U1 => write!(f, "bool"), IntegerBitSize::U8 => write!(f, "u8"), IntegerBitSize::U16 => write!(f, "u16"), @@ -121,7 +152,7 @@ impl std::fmt::Display for IntegerBitSize { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, PartialOrd, Ord, Hash)] pub enum BitSize { Field, Integer(IntegerBitSize), @@ -150,7 +181,7 @@ impl BitSize { /// While we are usually agnostic to how memory is passed within Brillig, /// this needs to be encoded somehow when dealing with an external system. /// For simplicity, the extra type information is given right in the ForeignCall instructions. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy, Hash)] pub enum ValueOrArray { /// A single value passed to or from an external call /// It is an 'immediate' value - used without dereferencing. @@ -167,7 +198,7 @@ pub enum ValueOrArray { HeapVector(HeapVector), } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] pub enum BrilligOpcode { /// Takes the fields in addresses `lhs` and `rhs` /// Performs the specified binary operation @@ -274,17 +305,16 @@ pub enum BrilligOpcode { BlackBox(BlackBoxOp), /// Used to denote execution failure, returning data after the offset Trap { - revert_data: HeapArray, + revert_data: HeapVector, }, /// Stop execution, returning data after the offset Stop { - return_data_offset: usize, - return_data_size: usize, + return_data: HeapVector, }, } /// Binary fixed-length field expressions -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)] pub enum BinaryFieldOp { Add, Sub, @@ -302,7 +332,7 @@ pub enum BinaryFieldOp { } /// Binary fixed-length integer expressions -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)] pub enum BinaryIntOp { Add, Sub, diff --git a/acvm-repo/brillig_vm/Cargo.toml b/acvm-repo/brillig_vm/Cargo.toml index a5e1f7182b1..8225244f9a7 100644 --- a/acvm-repo/brillig_vm/Cargo.toml +++ b/acvm-repo/brillig_vm/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig_vm" description = "The virtual machine that processes Brillig bytecode, used to introduce non-determinism to the ACVM" # x-release-please-start-version -version = "0.50.0" +version = "1.0.0-beta.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/brillig_vm/src/black_box.rs b/acvm-repo/brillig_vm/src/black_box.rs index 56f715c13a9..79aea2adf76 100644 --- a/acvm-repo/brillig_vm/src/black_box.rs +++ b/acvm-repo/brillig_vm/src/black_box.rs @@ -1,9 +1,8 @@ use acir::brillig::{BlackBoxOp, HeapArray, HeapVector, IntegerBitSize}; use acir::{AcirField, BlackBoxFunc}; -use acvm_blackbox_solver::BigIntSolver; use acvm_blackbox_solver::{ - aes128_encrypt, blake2s, blake3, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccak256, - keccakf1600, sha256_compression, BlackBoxFunctionSolver, BlackBoxResolutionError, + aes128_encrypt, blake2s, blake3, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccakf1600, + sha256_compression, BigIntSolverWithId, BlackBoxFunctionSolver, BlackBoxResolutionError, }; use num_bigint::BigUint; use num_traits::Zero; @@ -39,11 +38,13 @@ fn to_value_vec(input: &[u8]) -> Vec> { input.iter().map(|&x| x.into()).collect() } +pub(crate) type BrilligBigIntSolver = BigIntSolverWithId; + pub(crate) fn evaluate_black_box>( op: &BlackBoxOp, solver: &Solver, memory: &mut Memory, - bigint_solver: &mut BrilligBigintSolver, + bigint_solver: &mut BrilligBigIntSolver, ) -> Result<(), BlackBoxResolutionError> { match op { BlackBoxOp::AES128Encrypt { inputs, iv, key, outputs } => { @@ -56,7 +57,7 @@ pub(crate) fn evaluate_black_box })?; let key: [u8; 16] = to_u8_vec(read_heap_array(memory, key)).try_into().map_err(|_| { - BlackBoxResolutionError::Failed(bb_func, "Invalid ley length".to_string()) + BlackBoxResolutionError::Failed(bb_func, "Invalid key length".to_string()) })?; let ciphertext = aes128_encrypt(&inputs, iv, key)?; @@ -77,14 +78,8 @@ pub(crate) fn evaluate_black_box memory.write_slice(memory.read_ref(output.pointer), &to_value_vec(&bytes)); Ok(()) } - BlackBoxOp::Keccak256 { message, output } => { - let message = to_u8_vec(read_heap_vector(memory, message)); - let bytes = keccak256(message.as_slice())?; - memory.write_slice(memory.read_ref(output.pointer), &to_value_vec(&bytes)); - Ok(()) - } - BlackBoxOp::Keccakf1600 { message, output } => { - let state_vec: Vec = read_heap_vector(memory, message) + BlackBoxOp::Keccakf1600 { input, output } => { + let state_vec: Vec = read_heap_array(memory, input) .iter() .map(|&memory_value| memory_value.try_into().unwrap()) .collect(); @@ -146,17 +141,6 @@ pub(crate) fn evaluate_black_box memory.write(*result_address, result.into()); Ok(()) } - BlackBoxOp::SchnorrVerify { public_key_x, public_key_y, message, signature, result } => { - let public_key_x = *memory.read(*public_key_x).extract_field().unwrap(); - let public_key_y = *memory.read(*public_key_y).extract_field().unwrap(); - let message: Vec = to_u8_vec(read_heap_vector(memory, message)); - let signature: [u8; 64] = - to_u8_vec(read_heap_vector(memory, signature)).try_into().unwrap(); - let verified = - solver.schnorr_verify(&public_key_x, &public_key_y, &signature, &message)?; - memory.write(*result, verified.into()); - Ok(()) - } BlackBoxOp::MultiScalarMul { points, scalars, outputs: result } => { let points: Vec = read_heap_vector(memory, points) .iter() @@ -227,41 +211,6 @@ pub(crate) fn evaluate_black_box ); Ok(()) } - BlackBoxOp::PedersenCommitment { inputs, domain_separator, output } => { - let inputs: Vec = read_heap_vector(memory, inputs) - .iter() - .map(|x| *x.extract_field().unwrap()) - .collect(); - let domain_separator: u32 = - memory.read(*domain_separator).try_into().map_err(|_| { - BlackBoxResolutionError::Failed( - BlackBoxFunc::PedersenCommitment, - "Invalid separator length".to_string(), - ) - })?; - let (x, y) = solver.pedersen_commitment(&inputs, domain_separator)?; - memory.write_slice( - memory.read_ref(output.pointer), - &[MemoryValue::new_field(x), MemoryValue::new_field(y)], - ); - Ok(()) - } - BlackBoxOp::PedersenHash { inputs, domain_separator, output } => { - let inputs: Vec = read_heap_vector(memory, inputs) - .iter() - .map(|x| *x.extract_field().unwrap()) - .collect(); - let domain_separator: u32 = - memory.read(*domain_separator).try_into().map_err(|_| { - BlackBoxResolutionError::Failed( - BlackBoxFunc::PedersenCommitment, - "Invalid separator length".to_string(), - ) - })?; - let hash = solver.pedersen_hash(&inputs, domain_separator)?; - memory.write(*output, MemoryValue::new_field(hash)); - Ok(()) - } BlackBoxOp::BigIntAdd { lhs, rhs, output } => { let lhs = memory.read(*lhs).try_into().unwrap(); let rhs = memory.read(*rhs).try_into().unwrap(); @@ -333,7 +282,7 @@ pub(crate) fn evaluate_black_box } BlackBoxOp::Sha256Compression { input, hash_values, output } => { let mut message = [0; 16]; - let inputs = read_heap_vector(memory, input); + let inputs = read_heap_array(memory, input); if inputs.len() != 16 { return Err(BlackBoxResolutionError::Failed( BlackBoxFunc::Sha256Compression, @@ -344,7 +293,7 @@ pub(crate) fn evaluate_black_box message[i] = input.try_into().unwrap(); } let mut state = [0; 8]; - let values = read_heap_vector(memory, hash_values); + let values = read_heap_array(memory, hash_values); if values.len() != 8 { return Err(BlackBoxResolutionError::Failed( BlackBoxFunc::Sha256Compression, @@ -371,18 +320,18 @@ pub(crate) fn evaluate_black_box let mut input = BigUint::from_bytes_be(&input.to_be_bytes()); let radix = BigUint::from_bytes_be(&radix.to_be_bytes()); - let mut limbs: Vec> = Vec::with_capacity(output.size); + let mut limbs: Vec> = vec![MemoryValue::default(); output.size]; - for _ in 0..output.size { + for i in (0..output.size).rev() { let limb = &input % &radix; if *output_bits { - limbs.push(MemoryValue::new_integer( + limbs[i] = MemoryValue::new_integer( if limb.is_zero() { 0 } else { 1 }, IntegerBitSize::U1, - )); + ); } else { let limb: u8 = limb.try_into().unwrap(); - limbs.push(MemoryValue::new_integer(limb as u128, IntegerBitSize::U8)); + limbs[i] = MemoryValue::new_integer(limb as u128, IntegerBitSize::U8); }; input /= &radix; } @@ -394,64 +343,14 @@ pub(crate) fn evaluate_black_box } } -/// Wrapper over the generic bigint solver to automatically assign bigint ids in brillig -#[derive(Default, Debug, Clone, PartialEq, Eq)] -pub(crate) struct BrilligBigintSolver { - bigint_solver: BigIntSolver, - last_id: u32, -} - -impl BrilligBigintSolver { - pub(crate) fn create_bigint_id(&mut self) -> u32 { - let output = self.last_id; - self.last_id += 1; - output - } - - pub(crate) fn bigint_from_bytes( - &mut self, - inputs: &[u8], - modulus: &[u8], - ) -> Result { - let id = self.create_bigint_id(); - self.bigint_solver.bigint_from_bytes(inputs, modulus, id)?; - Ok(id) - } - - pub(crate) fn bigint_to_bytes(&self, input: u32) -> Result, BlackBoxResolutionError> { - self.bigint_solver.bigint_to_bytes(input) - } - - pub(crate) fn bigint_op( - &mut self, - lhs: u32, - rhs: u32, - func: BlackBoxFunc, - ) -> Result { - let modulus_lhs = self.bigint_solver.get_modulus(lhs, func)?; - let modulus_rhs = self.bigint_solver.get_modulus(rhs, func)?; - if modulus_lhs != modulus_rhs { - return Err(BlackBoxResolutionError::Failed( - func, - "moduli should be identical in BigInt operation".to_string(), - )); - } - let id = self.create_bigint_id(); - self.bigint_solver.bigint_op(lhs, rhs, id, func)?; - Ok(id) - } -} - fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { match op { BlackBoxOp::AES128Encrypt { .. } => BlackBoxFunc::AES128Encrypt, BlackBoxOp::Blake2s { .. } => BlackBoxFunc::Blake2s, BlackBoxOp::Blake3 { .. } => BlackBoxFunc::Blake3, - BlackBoxOp::Keccak256 { .. } => BlackBoxFunc::Keccak256, BlackBoxOp::Keccakf1600 { .. } => BlackBoxFunc::Keccakf1600, BlackBoxOp::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1, BlackBoxOp::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1, - BlackBoxOp::SchnorrVerify { .. } => BlackBoxFunc::SchnorrVerify, BlackBoxOp::MultiScalarMul { .. } => BlackBoxFunc::MultiScalarMul, BlackBoxOp::EmbeddedCurveAdd { .. } => BlackBoxFunc::EmbeddedCurveAdd, BlackBoxOp::BigIntAdd { .. } => BlackBoxFunc::BigIntAdd, @@ -463,7 +362,5 @@ fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { BlackBoxOp::Poseidon2Permutation { .. } => BlackBoxFunc::Poseidon2Permutation, BlackBoxOp::Sha256Compression { .. } => BlackBoxFunc::Sha256Compression, BlackBoxOp::ToRadix { .. } => unreachable!("ToRadix is not an ACIR BlackBoxFunc"), - BlackBoxOp::PedersenCommitment { .. } => BlackBoxFunc::PedersenCommitment, - BlackBoxOp::PedersenHash { .. } => BlackBoxFunc::PedersenHash, } } diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index 07d0ea02ad4..5b3688339b5 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -6,7 +6,6 @@ //! The Brillig VM is a specialized VM which allows the [ACVM][acvm] to perform custom non-determinism. //! //! Brillig bytecode is distinct from regular [ACIR][acir] in that it does not generate constraints. -//! This is a generalization over the fixed directives that exists within in the ACVM. //! //! [acir]: https://crates.io/crates/acir //! [acvm]: https://crates.io/crates/acvm @@ -18,7 +17,7 @@ use acir::brillig::{ use acir::AcirField; use acvm_blackbox_solver::BlackBoxFunctionSolver; use arithmetic::{evaluate_binary_field_op, evaluate_binary_int_op, BrilligArithmeticError}; -use black_box::{evaluate_black_box, BrilligBigintSolver}; +use black_box::{evaluate_black_box, BrilligBigIntSolver}; // Re-export `brillig`. pub use acir::brillig; @@ -63,6 +62,15 @@ pub enum VMStatus { }, } +// A sample for each opcode that was executed. +pub type BrilligProfilingSamples = Vec; + +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct BrilligProfilingSample { + // The call stack when processing a given opcode. + pub call_stack: Vec, +} + #[derive(Debug, PartialEq, Eq, Clone)] /// VM encapsulates the state of the Brillig VM during execution. pub struct VM<'a, F, B: BlackBoxFunctionSolver> { @@ -87,7 +95,11 @@ pub struct VM<'a, F, B: BlackBoxFunctionSolver> { /// The solver for blackbox functions black_box_solver: &'a B, // The solver for big integers - bigint_solver: BrilligBigintSolver, + bigint_solver: BrilligBigIntSolver, + // Flag that determines whether we want to profile VM. + profiling_active: bool, + // Samples for profiling the VM execution. + profiling_samples: BrilligProfilingSamples, } impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { @@ -97,6 +109,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { bytecode: &'a [Opcode], foreign_call_results: Vec>, black_box_solver: &'a B, + profiling_active: bool, ) -> Self { Self { calldata, @@ -109,9 +122,19 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { call_stack: Vec::new(), black_box_solver, bigint_solver: Default::default(), + profiling_active, + profiling_samples: Vec::with_capacity(bytecode.len()), } } + pub fn is_profiling_active(&self) -> bool { + self.profiling_active + } + + pub fn take_profiling_samples(&mut self) -> BrilligProfilingSamples { + std::mem::take(&mut self.profiling_samples) + } + /// Updates the current status of the VM. /// Returns the given status. fn status(&mut self, status: VMStatus) -> VMStatus { @@ -185,7 +208,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { } pub fn write_memory_at(&mut self, ptr: usize, value: MemoryValue) { - self.memory.write(MemoryAddress(ptr), value); + self.memory.write(MemoryAddress::direct(ptr), value); } /// Returns the VM's current call stack, including the actual program @@ -196,6 +219,15 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { /// Process a single opcode and modify the program counter. pub fn process_opcode(&mut self) -> VMStatus { + if self.profiling_active { + let call_stack: Vec = self.get_call_stack(); + self.profiling_samples.push(BrilligProfilingSample { call_stack }); + } + + self.process_opcode_internal() + } + + fn process_opcode_internal(&mut self) -> VMStatus { let opcode = &self.bytecode[self.program_counter]; match opcode { Opcode::BinaryFieldOp { op, lhs, rhs, destination: result } => { @@ -314,14 +346,26 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { self.increment_program_counter() } Opcode::Trap { revert_data } => { - if revert_data.size > 0 { - self.trap(self.memory.read_ref(revert_data.pointer).0, revert_data.size) + let revert_data_size = self.memory.read(revert_data.size).to_usize(); + if revert_data_size > 0 { + self.trap( + self.memory.read_ref(revert_data.pointer).unwrap_direct(), + revert_data_size, + ) } else { self.trap(0, 0) } } - Opcode::Stop { return_data_offset, return_data_size } => { - self.finish(*return_data_offset, *return_data_size) + Opcode::Stop { return_data } => { + let return_data_size = self.memory.read(return_data.size).to_usize(); + if return_data_size > 0 { + self.finish( + self.memory.read_ref(return_data.pointer).unwrap_direct(), + return_data_size, + ) + } else { + self.finish(0, 0) + } } Opcode::Load { destination: destination_address, source_pointer } => { // Convert our source_pointer to an address @@ -437,6 +481,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { size: usize, value_types: &[HeapValueType], ) -> Vec> { + assert!(!start.is_relative(), "read_slice_of_values_from_memory requires direct addresses"); if HeapValueType::all_simple(value_types) { self.memory.read_slice(start, size).to_vec() } else { @@ -449,20 +494,25 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { (0..size) .zip(value_types.iter().cycle()) .flat_map(|(i, value_type)| { - let value_address: MemoryAddress = (start.to_usize() + i).into(); + let value_address = start.offset(i); match value_type { HeapValueType::Simple(_) => { vec![self.memory.read(value_address)] } HeapValueType::Array { value_types, size } => { let array_address = self.memory.read_ref(value_address); - let items_start = MemoryAddress(array_address.to_usize() + 1); - self.read_slice_of_values_from_memory(items_start, *size, value_types) + + self.read_slice_of_values_from_memory( + array_address.offset(1), + *size, + value_types, + ) } HeapValueType::Vector { value_types } => { let vector_address = self.memory.read_ref(value_address); - let size_address = MemoryAddress(vector_address.to_usize() + 1); - let items_start = MemoryAddress(vector_address.to_usize() + 2); + let size_address = + MemoryAddress::direct(vector_address.unwrap_direct() + 1); + let items_start = vector_address.offset(2); let vector_size = self.memory.read(size_address).to_usize(); self.read_slice_of_values_from_memory( items_start, @@ -630,13 +680,17 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { values: &Vec, values_idx: &mut usize, value_type: &HeapValueType, - ) -> Result { + ) -> Result<(), String> { + assert!( + !destination.is_relative(), + "write_slice_of_values_to_memory requires direct addresses" + ); let mut current_pointer = destination; match value_type { HeapValueType::Simple(bit_size) => { self.write_value_to_memory(destination, &values[*values_idx], *bit_size)?; *values_idx += 1; - Ok(MemoryAddress(destination.to_usize() + 1)) + Ok(()) } HeapValueType::Array { value_types, size } => { for _ in 0..*size { @@ -649,18 +703,17 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { *len, )?; *values_idx += 1; - current_pointer = MemoryAddress(current_pointer.to_usize() + 1); + current_pointer = current_pointer.offset(1); } HeapValueType::Array { .. } => { - let destination = - MemoryAddress(self.memory.read_ref(current_pointer).0 + 1); + let destination = self.memory.read_ref(current_pointer).offset(1); self.write_slice_of_values_to_memory( destination, values, values_idx, typ, )?; - current_pointer = MemoryAddress(current_pointer.to_usize() + 1); + current_pointer = current_pointer.offset(1); } HeapValueType::Vector { .. } => { return Err(format!( @@ -671,7 +724,7 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { } } } - Ok(current_pointer) + Ok(()) } HeapValueType::Vector { .. } => { Err(format!("Unsupported returned type in foreign calls {:?}", value_type)) @@ -795,13 +848,13 @@ mod tests { let calldata = vec![]; let opcodes = [Opcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(27u128), }]; // Start VM - let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); @@ -809,7 +862,7 @@ mod tests { // The address at index `2` should have the value of 3 since we had an // add opcode let VM { memory, .. } = vm; - let output_value = memory.read(MemoryAddress::from(0)); + let output_value = memory.read(MemoryAddress::direct(0)); assert_eq!(output_value.to_field(), FieldElement::from(27u128)); } @@ -820,38 +873,38 @@ mod tests { let lhs = { calldata.push(2u128.into()); - MemoryAddress::from(calldata.len() - 1) + MemoryAddress::direct(calldata.len() - 1) }; let rhs = { calldata.push(2u128.into()); - MemoryAddress::from(calldata.len() - 1) + MemoryAddress::direct(calldata.len() - 1) }; - let destination = MemoryAddress::from(calldata.len()); + let destination = MemoryAddress::direct(calldata.len()); let opcodes = vec![ Opcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(2u64), }, Opcode::Const { - destination: MemoryAddress(1), + destination: MemoryAddress::direct(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), + destination_address: MemoryAddress::direct(0), + size_address: MemoryAddress::direct(0), + offset_address: MemoryAddress::direct(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 mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -878,38 +931,48 @@ mod tests { let opcodes = vec![ Opcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(2u64), }, Opcode::Const { - destination: MemoryAddress(1), + destination: MemoryAddress::direct(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), + destination_address: MemoryAddress::direct(0), + size_address: MemoryAddress::direct(0), + offset_address: MemoryAddress::direct(1), + }, + Opcode::Jump { location: 6 }, + Opcode::Const { + destination: MemoryAddress::direct(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + Opcode::Trap { + revert_data: HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(0), + }, }, - 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), + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), }, - Opcode::JumpIfNot { condition: MemoryAddress::from(2), location: 4 }, + Opcode::JumpIfNot { condition: MemoryAddress::direct(2), location: 4 }, Opcode::BinaryFieldOp { op: BinaryFieldOp::Add, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(2), + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), }, ]; - let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -921,8 +984,10 @@ mod tests { 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 output_cmp_value = vm.memory.read(MemoryAddress::from(2)); + let output_cmp_value = vm.memory.read(MemoryAddress::direct(2)); assert_eq!(output_cmp_value.to_field(), false.into()); let status = vm.process_opcode(); @@ -933,13 +998,13 @@ mod tests { status, VMStatus::Failure { reason: FailureReason::Trap { revert_data_offset: 0, revert_data_size: 0 }, - call_stack: vec![4] + call_stack: vec![5] } ); // The address at index `2` should have not changed as we jumped over the add opcode let VM { memory, .. } = vm; - let output_value = memory.read(MemoryAddress::from(2)); + let output_value = memory.read(MemoryAddress::direct(2)); assert_eq!(output_value.to_field(), false.into()); } @@ -947,30 +1012,39 @@ mod tests { fn cast_opcode() { let calldata: Vec = vec![((2_u128.pow(32)) - 1).into()]; + let value_address = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let zero_usize = MemoryAddress::direct(3); + let opcodes = &[ Opcode::Const { - destination: MemoryAddress(0), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(1u64), }, Opcode::Const { - destination: MemoryAddress(1), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress(0), - size_address: MemoryAddress(0), - offset_address: MemoryAddress(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, Opcode::Cast { - destination: MemoryAddress::from(1), - source: MemoryAddress::from(0), + destination: value_address, + source: value_address, bit_size: BitSize::Integer(IntegerBitSize::U8), }, - Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, + Opcode::Stop { + return_data: HeapVector { + pointer: one_usize, // Since value_address is direct(1) + size: one_usize, + }, + }, ]; - let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -985,7 +1059,7 @@ mod tests { let VM { memory, .. } = vm; - let casted_value = memory.read(MemoryAddress::from(1)); + let casted_value = memory.read(MemoryAddress::direct(1)); assert_eq!(casted_value.to_field(), (2_u128.pow(8) - 1).into()); } @@ -993,35 +1067,44 @@ mod tests { fn not_opcode() { let calldata: Vec = vec![(1_usize).into()]; + let value_address = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let zero_usize = MemoryAddress::direct(3); + let opcodes = &[ Opcode::Const { - destination: MemoryAddress(0), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(1u64), }, Opcode::Const { - destination: MemoryAddress(1), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress(0), - size_address: MemoryAddress(0), - offset_address: MemoryAddress(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, Opcode::Cast { - destination: MemoryAddress::from(1), - source: MemoryAddress::from(0), + destination: value_address, + source: value_address, bit_size: BitSize::Integer(IntegerBitSize::U128), }, Opcode::Not { - destination: MemoryAddress::from(1), - source: MemoryAddress::from(1), + destination: value_address, + source: value_address, bit_size: IntegerBitSize::U128, }, - Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, + Opcode::Stop { + return_data: HeapVector { + pointer: one_usize, // Since value_address is direct(1) + size: one_usize, + }, + }, ]; - let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -1039,7 +1122,7 @@ mod tests { let VM { memory, .. } = vm; let (negated_value, _) = memory - .read(MemoryAddress::from(1)) + .read(MemoryAddress::direct(1)) .extract_integer() .expect("Expected integer as the output of Not"); assert_eq!(negated_value, !1_u128); @@ -1051,23 +1134,23 @@ mod tests { let opcodes = &[ Opcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(3u64), }, Opcode::Const { - destination: MemoryAddress(1), + destination: MemoryAddress::direct(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), + destination_address: MemoryAddress::direct(0), + size_address: MemoryAddress::direct(0), + offset_address: MemoryAddress::direct(1), }, - Opcode::Mov { destination: MemoryAddress::from(2), source: MemoryAddress::from(0) }, + Opcode::Mov { destination: MemoryAddress::direct(2), source: MemoryAddress::direct(0) }, ]; - let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -1081,10 +1164,10 @@ mod tests { let VM { memory, .. } = vm; - let destination_value = memory.read(MemoryAddress::from(2)); + let destination_value = memory.read(MemoryAddress::direct(2)); assert_eq!(destination_value.to_field(), (1u128).into()); - let source_value = memory.read(MemoryAddress::from(0)); + let source_value = memory.read(MemoryAddress::direct(0)); assert_eq!(source_value.to_field(), (1u128).into()); } @@ -1095,44 +1178,44 @@ mod tests { let opcodes = &[ Opcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(4u64), }, Opcode::Const { - destination: MemoryAddress(1), + destination: MemoryAddress::direct(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), + destination_address: MemoryAddress::direct(0), + size_address: MemoryAddress::direct(0), + offset_address: MemoryAddress::direct(1), }, Opcode::Cast { - destination: MemoryAddress::from(0), - source: MemoryAddress::from(0), + destination: MemoryAddress::direct(0), + source: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U1), }, Opcode::Cast { - destination: MemoryAddress::from(1), - source: MemoryAddress::from(1), + destination: MemoryAddress::direct(1), + source: MemoryAddress::direct(1), bit_size: BitSize::Integer(IntegerBitSize::U1), }, Opcode::ConditionalMov { - destination: MemoryAddress(4), // Sets 3_u128 to memory address 4 - source_a: MemoryAddress(2), - source_b: MemoryAddress(3), - condition: MemoryAddress(0), + destination: MemoryAddress::direct(4), // Sets 3_u128 to memory address 4 + source_a: MemoryAddress::direct(2), + source_b: MemoryAddress::direct(3), + condition: MemoryAddress::direct(0), }, Opcode::ConditionalMov { - destination: MemoryAddress(5), // Sets 2_u128 to memory address 5 - source_a: MemoryAddress(2), - source_b: MemoryAddress(3), - condition: MemoryAddress(1), + destination: MemoryAddress::direct(5), // Sets 2_u128 to memory address 5 + source_a: MemoryAddress::direct(2), + source_b: MemoryAddress::direct(3), + condition: MemoryAddress::direct(1), }, ]; - let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -1151,10 +1234,10 @@ mod tests { let VM { memory, .. } = vm; - let destination_value = memory.read(MemoryAddress::from(4)); + let destination_value = memory.read(MemoryAddress::direct(4)); assert_eq!(destination_value.to_field(), (3_u128).into()); - let source_value = memory.read(MemoryAddress::from(5)); + let source_value = memory.read(MemoryAddress::direct(5)); assert_eq!(source_value.to_field(), (2_u128).into()); } @@ -1167,26 +1250,26 @@ mod tests { let calldata_copy_opcodes = vec![ Opcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(5u64), }, Opcode::Const { - destination: MemoryAddress(1), + destination: MemoryAddress::direct(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), + destination_address: MemoryAddress::direct(0), + size_address: MemoryAddress::direct(0), + offset_address: MemoryAddress::direct(1), }, ]; let cast_opcodes: Vec<_> = (0..calldata_size) .map(|index| Opcode::Cast { - destination: MemoryAddress::from(index), - source: MemoryAddress::from(index), + destination: MemoryAddress::direct(index), + source: MemoryAddress::direct(index), bit_size: BitSize::Integer(bit_size), }) .collect(); @@ -1194,33 +1277,33 @@ mod tests { let equal_opcode = Opcode::BinaryIntOp { bit_size, op: BinaryIntOp::Equals, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(2), + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), }; let not_equal_opcode = Opcode::BinaryIntOp { bit_size, op: BinaryIntOp::Equals, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(3), - destination: MemoryAddress::from(2), + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(3), + destination: MemoryAddress::direct(2), }; let less_than_opcode = Opcode::BinaryIntOp { bit_size, op: BinaryIntOp::LessThan, - lhs: MemoryAddress::from(3), - rhs: MemoryAddress::from(4), - destination: MemoryAddress::from(2), + lhs: MemoryAddress::direct(3), + rhs: MemoryAddress::direct(4), + destination: MemoryAddress::direct(2), }; let less_than_equal_opcode = Opcode::BinaryIntOp { bit_size, op: BinaryIntOp::LessThanEquals, - lhs: MemoryAddress::from(3), - rhs: MemoryAddress::from(4), - destination: MemoryAddress::from(2), + lhs: MemoryAddress::direct(3), + rhs: MemoryAddress::direct(4), + destination: MemoryAddress::direct(2), }; let opcodes: Vec<_> = calldata_copy_opcodes @@ -1228,7 +1311,7 @@ mod tests { .chain(cast_opcodes) .chain([equal_opcode, not_equal_opcode, less_than_opcode, less_than_equal_opcode]) .collect(); - let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver, false); // Calldata copy let status = vm.process_opcode(); @@ -1247,25 +1330,25 @@ mod tests { let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - let output_eq_value = vm.memory.read(MemoryAddress::from(2)); + let output_eq_value = vm.memory.read(MemoryAddress::direct(2)); assert_eq!(output_eq_value, true.into()); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - let output_neq_value = vm.memory.read(MemoryAddress::from(2)); + let output_neq_value = vm.memory.read(MemoryAddress::direct(2)); assert_eq!(output_neq_value, false.into()); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); - let lt_value = vm.memory.read(MemoryAddress::from(2)); + let lt_value = vm.memory.read(MemoryAddress::direct(2)); assert_eq!(lt_value, true.into()); let status = vm.process_opcode(); assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); - let lte_value = vm.memory.read(MemoryAddress::from(2)); + let lte_value = vm.memory.read(MemoryAddress::direct(2)); assert_eq!(lte_value, true.into()); } @@ -1281,10 +1364,10 @@ mod tests { fn brillig_write_memory(item_count: usize) -> Vec> { let integer_bit_size = MEMORY_ADDRESSING_BIT_SIZE; let bit_size = BitSize::Integer(integer_bit_size); - let r_i = MemoryAddress::from(0); - let r_len = MemoryAddress::from(1); - let r_tmp = MemoryAddress::from(2); - let r_pointer = MemoryAddress::from(3); + let r_i = MemoryAddress::direct(0); + let r_len = MemoryAddress::direct(1); + let r_tmp = MemoryAddress::direct(2); + let r_pointer = MemoryAddress::direct(3); let start: [Opcode; 3] = [ // i = 0 @@ -1346,17 +1429,17 @@ mod tests { fn iconst_opcode() { let opcodes = &[ Opcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(MEMORY_ADDRESSING_BIT_SIZE), value: FieldElement::from(8_usize), }, Opcode::IndirectConst { - destination_pointer: MemoryAddress(0), + destination_pointer: MemoryAddress::direct(0), bit_size: BitSize::Integer(MEMORY_ADDRESSING_BIT_SIZE), value: FieldElement::from(27_usize), }, ]; - let mut vm = VM::new(vec![], opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(vec![], opcodes, vec![], &StubbedBlackBoxSolver, false); let status = vm.process_opcode(); assert_eq!(status, VMStatus::InProgress); @@ -1366,7 +1449,7 @@ mod tests { let VM { memory, .. } = vm; - let destination_value = memory.read(MemoryAddress::from(8)); + let destination_value = memory.read(MemoryAddress::direct(8)); assert_eq!(destination_value.to_field(), (27_usize).into()); } @@ -1382,11 +1465,11 @@ mod tests { /// } fn brillig_sum_memory(memory: Vec) -> FieldElement { let bit_size = IntegerBitSize::U32; - let r_i = MemoryAddress::from(0); - let r_len = MemoryAddress::from(1); - let r_sum = MemoryAddress::from(2); - let r_tmp = MemoryAddress::from(3); - let r_pointer = MemoryAddress::from(4); + let r_i = MemoryAddress::direct(0); + let r_len = MemoryAddress::direct(1); + let r_sum = MemoryAddress::direct(2); + let r_tmp = MemoryAddress::direct(3); + let r_pointer = MemoryAddress::direct(4); let start = [ // sum = 0 @@ -1410,19 +1493,19 @@ mod tests { bit_size: BitSize::Integer(bit_size), }, Opcode::Const { - destination: MemoryAddress(100), + destination: MemoryAddress::direct(100), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(memory.len() as u32), }, Opcode::Const { - destination: MemoryAddress(101), + destination: MemoryAddress::direct(101), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress(5), - size_address: MemoryAddress(100), - offset_address: MemoryAddress(101), + destination_address: MemoryAddress::direct(5), + size_address: MemoryAddress::direct(100), + offset_address: MemoryAddress::direct(101), }, ]; let loop_body = [ @@ -1501,10 +1584,10 @@ mod tests { fn brillig_recursive_write_memory(size: usize) -> Vec> { let integer_bit_size = MEMORY_ADDRESSING_BIT_SIZE; let bit_size = BitSize::Integer(integer_bit_size); - let r_i = MemoryAddress::from(0); - let r_len = MemoryAddress::from(1); - let r_tmp = MemoryAddress::from(2); - let r_pointer = MemoryAddress::from(3); + let r_i = MemoryAddress::direct(0); + let r_len = MemoryAddress::direct(1); + let r_tmp = MemoryAddress::direct(2); + let r_pointer = MemoryAddress::direct(3); let start: [Opcode; 5] = [ // i = 0 @@ -1580,7 +1663,7 @@ mod tests { calldata: Vec, opcodes: &[Opcode], ) -> VM<'_, F, StubbedBlackBoxSolver> { - let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver); + let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); brillig_execute(&mut vm); assert_eq!(vm.call_stack, vec![]); vm @@ -1598,8 +1681,8 @@ mod tests { #[test] fn foreign_call_opcode_simple_result() { - let r_input = MemoryAddress::from(0); - let r_result = MemoryAddress::from(1); + let r_input = MemoryAddress::direct(0); + let r_result = MemoryAddress::direct(1); let double_program = vec![ // Load input address with value 5 @@ -1654,8 +1737,8 @@ mod tests { #[test] fn foreign_call_opcode_memory_result() { - let r_input = MemoryAddress::from(0); - let r_output = MemoryAddress::from(1); + let r_input = MemoryAddress::direct(0); + let r_output = MemoryAddress::direct(1); // Define a simple 2x2 matrix in memory let initial_matrix: Vec = @@ -1667,19 +1750,19 @@ mod tests { let invert_program = vec![ Opcode::Const { - destination: MemoryAddress(0), + destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(initial_matrix.len() as u32), }, Opcode::Const { - destination: MemoryAddress(1), + destination: MemoryAddress::direct(1), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress(2), - size_address: MemoryAddress(0), - offset_address: MemoryAddress(1), + destination_address: MemoryAddress::direct(2), + size_address: MemoryAddress::direct(0), + offset_address: MemoryAddress::direct(1), }, // input = 0 Opcode::Const { @@ -1736,7 +1819,7 @@ mod tests { assert_eq!(vm.status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); // Check result in memory - let result_values = vm.memory.read_slice(MemoryAddress(2), 4).to_vec(); + let result_values = vm.memory.read_slice(MemoryAddress::direct(2), 4).to_vec(); assert_eq!( result_values.into_iter().map(|mem_value| mem_value.to_field()).collect::>(), expected_result @@ -1749,11 +1832,11 @@ mod tests { /// Calling a simple foreign call function that takes any string input, concatenates it with itself, and reverses the concatenation #[test] fn foreign_call_opcode_vector_input_and_output() { - let r_input_pointer = MemoryAddress::from(0); - let r_input_size = MemoryAddress::from(1); + let r_input_pointer = MemoryAddress::direct(0); + let r_input_size = MemoryAddress::direct(1); // We need to pass a location of appropriate size - let r_output_pointer = MemoryAddress::from(2); - let r_output_size = MemoryAddress::from(3); + let r_output_pointer = MemoryAddress::direct(2); + let r_output_size = MemoryAddress::direct(3); // Our first string to use the identity function with let input_string: Vec = @@ -1767,19 +1850,19 @@ mod tests { // First call: let string_double_program = vec![ Opcode::Const { - destination: MemoryAddress(100), + destination: MemoryAddress::direct(100), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(input_string.len() as u32), }, Opcode::Const { - destination: MemoryAddress(101), + destination: MemoryAddress::direct(101), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress(4), - size_address: MemoryAddress(100), - offset_address: MemoryAddress(101), + destination_address: MemoryAddress::direct(4), + size_address: MemoryAddress::direct(100), + offset_address: MemoryAddress::direct(101), }, // input_pointer = 4 Opcode::Const { @@ -1850,7 +1933,7 @@ mod tests { // Check result in memory let result_values: Vec<_> = vm .memory - .read_slice(MemoryAddress(4 + input_string.len()), output_string.len()) + .read_slice(MemoryAddress::direct(4 + input_string.len()), output_string.len()) .iter() .map(|mem_val| mem_val.clone().to_field()) .collect(); @@ -1862,8 +1945,8 @@ mod tests { #[test] fn foreign_call_opcode_memory_alloc_result() { - let r_input = MemoryAddress::from(0); - let r_output = MemoryAddress::from(1); + let r_input = MemoryAddress::direct(0); + let r_output = MemoryAddress::direct(1); // Define a simple 2x2 matrix in memory let initial_matrix: Vec = @@ -1875,19 +1958,19 @@ mod tests { let invert_program = vec![ Opcode::Const { - destination: MemoryAddress(100), + destination: MemoryAddress::direct(100), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(initial_matrix.len() as u32), }, Opcode::Const { - destination: MemoryAddress(101), + destination: MemoryAddress::direct(101), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress(2), - size_address: MemoryAddress(100), - offset_address: MemoryAddress(101), + destination_address: MemoryAddress::direct(2), + size_address: MemoryAddress::direct(100), + offset_address: MemoryAddress::direct(101), }, // input = 0 Opcode::Const { @@ -1946,7 +2029,7 @@ mod tests { // Check initial memory still in place let initial_values: Vec<_> = vm .memory - .read_slice(MemoryAddress(2), 4) + .read_slice(MemoryAddress::direct(2), 4) .iter() .map(|mem_val| mem_val.clone().to_field()) .collect(); @@ -1955,7 +2038,7 @@ mod tests { // Check result in memory let result_values: Vec<_> = vm .memory - .read_slice(MemoryAddress(6), 4) + .read_slice(MemoryAddress::direct(6), 4) .iter() .map(|mem_val| mem_val.clone().to_field()) .collect(); @@ -1967,9 +2050,9 @@ mod tests { #[test] fn foreign_call_opcode_multiple_array_inputs_result() { - let r_input_a = MemoryAddress::from(0); - let r_input_b = MemoryAddress::from(1); - let r_output = MemoryAddress::from(2); + let r_input_a = MemoryAddress::direct(0); + let r_input_b = MemoryAddress::direct(1); + let r_output = MemoryAddress::direct(2); // Define a simple 2x2 matrix in memory let matrix_a: Vec = @@ -1984,19 +2067,19 @@ mod tests { let matrix_mul_program = vec![ Opcode::Const { - destination: MemoryAddress(100), + destination: MemoryAddress::direct(100), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(matrix_a.len() + matrix_b.len()), }, Opcode::Const { - destination: MemoryAddress(101), + destination: MemoryAddress::direct(101), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress(3), - size_address: MemoryAddress(100), - offset_address: MemoryAddress(101), + destination_address: MemoryAddress::direct(3), + size_address: MemoryAddress::direct(100), + offset_address: MemoryAddress::direct(101), }, // input = 3 Opcode::Const { @@ -2068,7 +2151,7 @@ mod tests { // Check result in memory let result_values: Vec<_> = vm .memory - .read_slice(MemoryAddress(0), 4) + .read_slice(MemoryAddress::direct(0), 4) .iter() .map(|mem_val| mem_val.clone().to_field()) .collect(); @@ -2135,30 +2218,30 @@ mod tests { // memory address of the end of the above data structures let r_ptr = memory.len(); - let r_input = MemoryAddress::from(r_ptr); - let r_output = MemoryAddress::from(r_ptr + 1); + let r_input = MemoryAddress::direct(r_ptr); + let r_output = MemoryAddress::direct(r_ptr + 1); let program: Vec<_> = vec![ Opcode::Const { - destination: MemoryAddress(100), + destination: MemoryAddress::direct(100), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(memory.len()), }, Opcode::Const { - destination: MemoryAddress(101), + destination: MemoryAddress::direct(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), + destination_address: MemoryAddress::direct(0), + size_address: MemoryAddress::direct(100), + offset_address: MemoryAddress::direct(101), }, ] .into_iter() .chain(memory.iter().enumerate().map(|(index, mem_value)| Opcode::Cast { - destination: MemoryAddress(index), - source: MemoryAddress(index), + destination: MemoryAddress::direct(index), + source: MemoryAddress::direct(index), bit_size: mem_value.bit_size(), })) .chain(vec![ @@ -2227,4 +2310,49 @@ mod tests { // Ensure the foreign call counter has been incremented assert_eq!(vm.foreign_call_counter, 1); } + + #[test] + fn relative_addressing() { + let calldata = vec![]; + let bit_size = BitSize::Integer(IntegerBitSize::U32); + let value = FieldElement::from(3u128); + + let opcodes = [ + Opcode::Const { + destination: MemoryAddress::direct(0), + bit_size, + value: FieldElement::from(27u128), + }, + Opcode::Const { + destination: MemoryAddress::relative(1), // Resolved address 28 value 3 + bit_size, + value, + }, + Opcode::Const { + destination: MemoryAddress::direct(1), // Address 1 value 3 + bit_size, + value, + }, + Opcode::BinaryIntOp { + destination: MemoryAddress::direct(1), + op: BinaryIntOp::Equals, + bit_size: IntegerBitSize::U32, + lhs: MemoryAddress::direct(1), + rhs: MemoryAddress::direct(28), + }, + ]; + + let mut vm = VM::new(calldata, &opcodes, vec![], &StubbedBlackBoxSolver, false); + + vm.process_opcode(); + vm.process_opcode(); + vm.process_opcode(); + let status = vm.process_opcode(); + assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); + + let VM { memory, .. } = vm; + let output_value = memory.read(MemoryAddress::direct(1)); + + assert_eq!(output_value.to_field(), FieldElement::from(1u128)); + } } diff --git a/acvm-repo/brillig_vm/src/memory.rs b/acvm-repo/brillig_vm/src/memory.rs index ef1e0301387..2bf45f77b54 100644 --- a/acvm-repo/brillig_vm/src/memory.rs +++ b/acvm-repo/brillig_vm/src/memory.rs @@ -136,7 +136,7 @@ impl std::fmt::Display for MemoryValue { impl Default for MemoryValue { fn default() -> Self { - MemoryValue::new_integer(0, IntegerBitSize::U0) + MemoryValue::new_field(F::zero()) } } @@ -233,13 +233,25 @@ pub struct Memory { } impl Memory { - /// Gets the value at pointer - pub fn read(&self, ptr: MemoryAddress) -> MemoryValue { - self.inner.get(ptr.to_usize()).copied().unwrap_or_default() + fn get_stack_pointer(&self) -> usize { + self.read(MemoryAddress::Direct(0)).to_usize() + } + + fn resolve(&self, address: MemoryAddress) -> usize { + match address { + MemoryAddress::Direct(address) => address, + MemoryAddress::Relative(offset) => self.get_stack_pointer() + offset, + } + } + + /// Gets the value at address + pub fn read(&self, address: MemoryAddress) -> MemoryValue { + let resolved_addr = self.resolve(address); + self.inner.get(resolved_addr).copied().unwrap_or_default() } pub fn read_ref(&self, ptr: MemoryAddress) -> MemoryAddress { - MemoryAddress(self.read(ptr).to_usize()) + MemoryAddress::direct(self.read(ptr).to_usize()) } pub fn read_slice(&self, addr: MemoryAddress, len: usize) -> &[MemoryValue] { @@ -249,13 +261,15 @@ impl Memory { if len == 0 { return &[]; } - &self.inner[addr.to_usize()..(addr.to_usize() + len)] + let resolved_addr = self.resolve(addr); + &self.inner[resolved_addr..(resolved_addr + len)] } - /// Sets the value at pointer `ptr` to `value` - pub fn write(&mut self, ptr: MemoryAddress, value: MemoryValue) { - self.resize_to_fit(ptr.to_usize() + 1); - self.inner[ptr.to_usize()] = value; + /// Sets the value at `address` to `value` + pub fn write(&mut self, address: MemoryAddress, value: MemoryValue) { + let resolved_ptr = self.resolve(address); + self.resize_to_fit(resolved_ptr + 1); + self.inner[resolved_ptr] = value; } fn resize_to_fit(&mut self, size: usize) { @@ -265,10 +279,11 @@ impl Memory { self.inner.resize(new_size, MemoryValue::default()); } - /// Sets the values after pointer `ptr` to `values` - pub fn write_slice(&mut self, ptr: MemoryAddress, values: &[MemoryValue]) { - self.resize_to_fit(ptr.to_usize() + values.len()); - self.inner[ptr.to_usize()..(ptr.to_usize() + values.len())].copy_from_slice(values); + /// Sets the values after `address` to `values` + pub fn write_slice(&mut self, address: MemoryAddress, values: &[MemoryValue]) { + let resolved_address = self.resolve(address); + self.resize_to_fit(resolved_address + values.len()); + self.inner[resolved_address..(resolved_address + values.len())].copy_from_slice(values); } /// Returns the values of the memory diff --git a/compiler/fm/src/file_map.rs b/compiler/fm/src/file_map.rs index ba552fe5156..857c7460fb9 100644 --- a/compiler/fm/src/file_map.rs +++ b/compiler/fm/src/file_map.rs @@ -80,6 +80,19 @@ impl FileMap { pub fn all_file_ids(&self) -> impl Iterator { self.name_to_id.values() } + + pub fn get_name(&self, file_id: FileId) -> Result { + let name = self.files.get(file_id.as_usize())?.name().clone(); + + // See if we can make the file name a bit shorter/easier to read if it starts with the current directory + if let Some(current_dir) = &self.current_dir { + if let Ok(name_without_prefix) = name.0.strip_prefix(current_dir) { + return Ok(PathString::from_path(name_without_prefix.to_path_buf())); + } + } + + Ok(name) + } } impl Default for FileMap { fn default() -> Self { @@ -97,16 +110,7 @@ impl<'a> Files<'a> for FileMap { type Source = &'a str; fn name(&self, file_id: Self::FileId) -> Result { - let name = self.files.get(file_id.as_usize())?.name().clone(); - - // See if we can make the file name a bit shorter/easier to read if it starts with the current directory - if let Some(current_dir) = &self.current_dir { - if let Ok(name_without_prefix) = name.0.strip_prefix(current_dir) { - return Ok(PathString::from_path(name_without_prefix.to_path_buf())); - } - } - - Ok(name) + self.get_name(file_id) } fn source(&'a self, file_id: Self::FileId) -> Result { diff --git a/compiler/fm/src/lib.rs b/compiler/fm/src/lib.rs index 37da29fc982..fad2634bab4 100644 --- a/compiler/fm/src/lib.rs +++ b/compiler/fm/src/lib.rs @@ -100,6 +100,11 @@ impl FileManager { self.id_to_path.get(&file_id).map(|path| path.as_path()) } + pub fn has_file(&self, file_name: &Path) -> bool { + let file_name = self.root.join(file_name); + self.name_to_id(file_name).is_some() + } + // TODO: This should accept a &Path instead of a PathBuf pub fn name_to_id(&self, file_name: PathBuf) -> Option { self.file_map.get_file_id(&PathString::from_path(file_name)) diff --git a/compiler/integration-tests/package.json b/compiler/integration-tests/package.json index 64a638539d5..bfaa1cabd16 100644 --- a/compiler/integration-tests/package.json +++ b/compiler/integration-tests/package.json @@ -1,34 +1,34 @@ { - "name": "integration-tests", - "license": "(MIT OR Apache-2.0)", - "main": "index.js", - "private": true, - "scripts": { - "build": "echo Integration Test build step", - "test": "yarn test:browser && yarn test:node", - "test:node": "bash ./scripts/setup.sh && hardhat test test/node/prove_and_verify.test.ts && hardhat test test/node/smart_contract_verifier.test.ts && hardhat test test/node/onchain_recursive_verification.test.ts", - "test:browser": "web-test-runner", - "test:integration:browser": "web-test-runner test/browser/**/*.test.ts", - "test:integration:browser:watch": "web-test-runner test/browser/**/*.test.ts --watch", - "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" - }, - "dependencies": { - "@noir-lang/backend_barretenberg": "workspace:*", - "@noir-lang/noir_js": "workspace:*", - "@noir-lang/noir_wasm": "workspace:*", - "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", - "@nomicfoundation/hardhat-ethers": "^3.0.0", - "@web/dev-server-esbuild": "^0.3.6", - "@web/dev-server-import-maps": "^0.2.0", - "@web/test-runner": "^0.18.1", - "@web/test-runner-playwright": "^0.11.0", - "eslint": "^8.57.0", - "eslint-plugin-prettier": "^5.1.3", - "ethers": "^6.7.1", - "hardhat": "^2.22.6", - "prettier": "3.2.5", - "smol-toml": "^1.1.2", - "toml": "^3.0.0", - "tslog": "^4.9.2" - } + "name": "integration-tests", + "license": "(MIT OR Apache-2.0)", + "main": "index.js", + "private": true, + "scripts": { + "build": "echo Integration Test build step", + "test": "yarn test:browser && yarn test:node", + "test:node": "bash ./scripts/setup.sh && hardhat test test/node/prove_and_verify.test.ts && hardhat test test/node/smart_contract_verifier.test.ts && hardhat test test/node/onchain_recursive_verification.test.ts", + "test:browser": "web-test-runner", + "test:integration:browser": "web-test-runner test/browser/**/*.test.ts", + "test:integration:browser:watch": "web-test-runner test/browser/**/*.test.ts --watch", + "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" + }, + "dependencies": { + "@aztec/bb.js": "0.66.0", + "@noir-lang/noir_js": "workspace:*", + "@noir-lang/noir_wasm": "workspace:*", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@web/dev-server-esbuild": "^0.3.6", + "@web/dev-server-import-maps": "^0.2.0", + "@web/test-runner": "^0.18.1", + "@web/test-runner-playwright": "^0.11.0", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", + "ethers": "^6.7.1", + "hardhat": "^2.22.6", + "prettier": "3.2.5", + "smol-toml": "^1.1.2", + "toml": "^3.0.0", + "tslog": "^4.9.2" + } } diff --git a/compiler/integration-tests/scripts/codegen-verifiers.sh b/compiler/integration-tests/scripts/codegen-verifiers.sh index bec59eb6889..de1f71a4cc0 100755 --- a/compiler/integration-tests/scripts/codegen-verifiers.sh +++ b/compiler/integration-tests/scripts/codegen-verifiers.sh @@ -17,8 +17,8 @@ KEYS=$(mktemp -d) # Codegen verifier contract for 1_mul mul_dir=$repo_root/test_programs/execution_success/1_mul nargo --program-dir $mul_dir compile -$NARGO_BACKEND_PATH write_vk -b $mul_dir/target/1_mul.json -o $KEYS/1_mul -$NARGO_BACKEND_PATH contract -k $KEYS/1_mul -o $contracts_dir/1_mul.sol +$NARGO_BACKEND_PATH write_vk -b $mul_dir/target/1_mul.json -o $KEYS/1_mul +$NARGO_BACKEND_PATH contract -k $KEYS/1_mul -o $contracts_dir/1_mul.sol # Codegen verifier contract for assert_statement assert_statement_dir=$repo_root/test_programs/execution_success/assert_statement diff --git a/compiler/integration-tests/test/browser/compile_prove_verify.test.ts b/compiler/integration-tests/test/browser/compile_prove_verify.test.ts index f18ceb85276..8d24b27ac25 100644 --- a/compiler/integration-tests/test/browser/compile_prove_verify.test.ts +++ b/compiler/integration-tests/test/browser/compile_prove_verify.test.ts @@ -4,7 +4,7 @@ import * as TOML from 'smol-toml'; import { compile, createFileManager } from '@noir-lang/noir_wasm'; import { Noir } from '@noir-lang/noir_js'; import { InputMap } from '@noir-lang/noirc_abi'; -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { UltraPlonkBackend } from '@aztec/bb.js'; import { getFile } from './utils.js'; @@ -59,7 +59,7 @@ test_cases.forEach((testInfo) => { const program = new Noir(noir_program); const { witness } = await program.execute(inputs); - const backend = new BarretenbergBackend(noir_program); + const backend = new UltraPlonkBackend(noir_program.bytecode); const proof = await backend.generateProof(witness); // JS verification diff --git a/compiler/integration-tests/test/browser/recursion.test.ts b/compiler/integration-tests/test/browser/recursion.test.ts index abbee7b96ad..71d6697f843 100644 --- a/compiler/integration-tests/test/browser/recursion.test.ts +++ b/compiler/integration-tests/test/browser/recursion.test.ts @@ -5,7 +5,7 @@ import { Logger } from 'tslog'; import { acvm, abi, Noir } from '@noir-lang/noir_js'; import * as TOML from 'smol-toml'; -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { UltraPlonkBackend } from '@aztec/bb.js'; import { getFile } from './utils.js'; import { Field, InputMap } from '@noir-lang/noirc_abi'; import { createFileManager, compile } from '@noir-lang/noir_wasm'; @@ -19,7 +19,7 @@ await newABICoder(); await initACVM(); const base_relative_path = '../../../../..'; -const circuit_main = 'test_programs/execution_success/assert_statement_recursive'; +const circuit_main = 'test_programs/execution_success/assert_statement'; const circuit_recursion = 'compiler/integration-tests/circuits/recursion'; async function getCircuit(projectPath: string) { @@ -45,7 +45,7 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. const main_program = await getCircuit(`${base_relative_path}/${circuit_main}`); const main_inputs: InputMap = TOML.parse(circuit_main_toml) as InputMap; - const main_backend = new BarretenbergBackend(main_program); + const main_backend = new UltraPlonkBackend(main_program.bytecode, {}, { recursive: true }); const { witness: main_witnessUint8Array } = await new Noir(main_program).execute(main_inputs); @@ -73,7 +73,7 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. const recursion_program = await getCircuit(`${base_relative_path}/${circuit_recursion}`); - const recursion_backend = new BarretenbergBackend(recursion_program); + const recursion_backend = new UltraPlonkBackend(recursion_program.bytecode, {}, { recursive: false }); const { witness: recursion_witnessUint8Array } = await new Noir(recursion_program).execute(recursion_inputs); diff --git a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts index f4647c478f1..1694da28805 100644 --- a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts +++ b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts @@ -6,7 +6,7 @@ import { resolve, join } from 'path'; import toml from 'toml'; import { Noir } from '@noir-lang/noir_js'; -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { UltraPlonkBackend } from '@aztec/bb.js'; import { Field, InputMap } from '@noir-lang/noirc_abi'; import { compile, createFileManager } from '@noir-lang/noir_wasm'; @@ -17,7 +17,7 @@ it.skip(`smart contract can verify a recursive proof`, async () => { const fm = createFileManager(basePath); const innerCompilationResult = await compile( fm, - join(basePath, './test_programs/execution_success/assert_statement_recursive'), + join(basePath, './test_programs/execution_success/assert_statement'), ); if (!('program' in innerCompilationResult)) { throw new Error('Compilation failed'); @@ -35,11 +35,11 @@ it.skip(`smart contract can verify a recursive proof`, async () => { // Intermediate proof - const inner_backend = new BarretenbergBackend(innerProgram); + const inner_backend = new UltraPlonkBackend(innerProgram.bytecode, {}, { recursive: true }); const inner = new Noir(innerProgram); const inner_prover_toml = readFileSync( - join(basePath, `./test_programs/execution_success/assert_statement_recursive/Prover.toml`), + join(basePath, `./test_programs/execution_success/assert_statement/Prover.toml`), ).toString(); const inner_inputs = toml.parse(inner_prover_toml); @@ -67,7 +67,7 @@ it.skip(`smart contract can verify a recursive proof`, async () => { const { witness: recursionWitness } = await recursion.execute(recursion_inputs); - const recursion_backend = new BarretenbergBackend(recursionProgram); + const recursion_backend = new UltraPlonkBackend(recursionProgram.bytecode, {}, { recursive: false }); const recursion_proof = await recursion_backend.generateProof(recursionWitness); expect(await recursion_backend.verifyProof(recursion_proof)).to.be.true; diff --git a/compiler/integration-tests/test/node/prove_and_verify.test.ts b/compiler/integration-tests/test/node/prove_and_verify.test.ts index babc8ca5bb8..4353bccd90d 100644 --- a/compiler/integration-tests/test/node/prove_and_verify.test.ts +++ b/compiler/integration-tests/test/node/prove_and_verify.test.ts @@ -2,18 +2,13 @@ import { expect } from 'chai'; import assert_lt_json from '../../circuits/assert_lt/target/assert_lt.json' assert { type: 'json' }; import fold_fibonacci_json from '../../circuits/fold_fibonacci/target/fold_fibonacci.json' assert { type: 'json' }; import { Noir } from '@noir-lang/noir_js'; -import { - BarretenbergBackend as Backend, - BarretenbergVerifier as Verifier, - UltraHonkBackend, - UltraHonkVerifier, -} from '@noir-lang/backend_barretenberg'; +import { BarretenbergVerifier, UltraPlonkBackend, UltraHonkBackend } from '@aztec/bb.js'; import { CompiledCircuit } from '@noir-lang/types'; const assert_lt_program = assert_lt_json as CompiledCircuit; const fold_fibonacci_program = fold_fibonacci_json as CompiledCircuit; -const backend = new Backend(assert_lt_program); +const backend = new UltraPlonkBackend(assert_lt_program.bytecode); it('end-to-end proof creation and verification (outer)', async () => { // Noir.Js part @@ -53,8 +48,8 @@ it('end-to-end proof creation and verification (outer) -- Verifier API', async ( const verificationKey = await backend.getVerificationKey(); // Proof verification - const verifier = new Verifier(); - const isValid = await verifier.verifyProof(proof, verificationKey); + const verifier = new BarretenbergVerifier(); + const isValid = await verifier.verifyUltraPlonkProof(proof, verificationKey); expect(isValid).to.be.true; }); @@ -94,7 +89,7 @@ it('end-to-end proving and verification with different instances', async () => { // bb.js part const proof = await backend.generateProof(witness); - const verifier = new Backend(assert_lt_program); + const verifier = new UltraPlonkBackend(assert_lt_program.bytecode); const proof_is_valid = await verifier.verifyProof(proof); expect(proof_is_valid).to.be.true; }); @@ -148,7 +143,7 @@ it('end-to-end proof creation and verification for multiple ACIR circuits (inner // bb.js part // // Proof creation - const backend = new Backend(fold_fibonacci_program); + const backend = new UltraPlonkBackend(fold_fibonacci_program.bytecode); const proof = await backend.generateProof(witness); // Proof verification @@ -156,7 +151,7 @@ it('end-to-end proof creation and verification for multiple ACIR circuits (inner expect(isValid).to.be.true; }); -const honkBackend = new UltraHonkBackend(assert_lt_program); +const honkBackend = new UltraHonkBackend(assert_lt_program.bytecode); it('UltraHonk end-to-end proof creation and verification (outer)', async () => { // Noir.Js part @@ -196,8 +191,8 @@ it('UltraHonk end-to-end proof creation and verification (outer) -- Verifier API const verificationKey = await honkBackend.getVerificationKey(); // Proof verification - const verifier = new UltraHonkVerifier(); - const isValid = await verifier.verifyProof(proof, verificationKey); + const verifier = new BarretenbergVerifier(); + const isValid = await verifier.verifyUltraHonkProof(proof, verificationKey); expect(isValid).to.be.true; }); @@ -236,7 +231,7 @@ it('UltraHonk end-to-end proving and verification with different instances', asy // bb.js part const proof = await honkBackend.generateProof(witness); - const verifier = new UltraHonkBackend(assert_lt_program); + const verifier = new UltraHonkBackend(assert_lt_program.bytecode); const proof_is_valid = await verifier.verifyProof(proof); expect(proof_is_valid).to.be.true; }); @@ -283,7 +278,7 @@ it('UltraHonk end-to-end proof creation and verification for multiple ACIR circu // bb.js part // // Proof creation - const honkBackend = new UltraHonkBackend(fold_fibonacci_program); + const honkBackend = new UltraHonkBackend(fold_fibonacci_program.bytecode); const proof = await honkBackend.generateProof(witness); // Proof verification diff --git a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts index e109cbcab6a..74a36262829 100644 --- a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts +++ b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts @@ -6,7 +6,7 @@ import { resolve } from 'path'; import toml from 'toml'; import { Noir } from '@noir-lang/noir_js'; -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { UltraPlonkBackend } from '@aztec/bb.js'; import { compile, createFileManager } from '@noir-lang/noir_wasm'; @@ -46,7 +46,7 @@ test_cases.forEach((testInfo) => { const inputs = toml.parse(prover_toml); const { witness } = await program.execute(inputs); - const backend = new BarretenbergBackend(noir_program); + const backend = new UltraPlonkBackend(noir_program.bytecode, {}, { recursive: false }); const proofData = await backend.generateProof(witness); // JS verification diff --git a/compiler/noirc_driver/src/abi_gen.rs b/compiler/noirc_driver/src/abi_gen.rs index be89b24fee5..625a35c8d15 100644 --- a/compiler/noirc_driver/src/abi_gen.rs +++ b/compiler/noirc_driver/src/abi_gen.rs @@ -6,14 +6,20 @@ use iter_extended::vecmap; use noirc_abi::{ Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue, AbiVisibility, Sign, }; +use noirc_errors::Span; +use noirc_evaluator::ErrorType; use noirc_frontend::ast::{Signedness, Visibility}; +use noirc_frontend::TypeBinding; use noirc_frontend::{ hir::Context, - hir_def::{expr::HirArrayLiteral, function::Param, stmt::HirPattern, types::Type}, - macros_api::{HirExpression, HirLiteral}, + hir_def::{ + expr::{HirArrayLiteral, HirExpression, HirLiteral}, + function::Param, + stmt::HirPattern, + types::Type, + }, node_interner::{FuncId, NodeInterner}, }; -use noirc_frontend::{TypeBinding, TypeVariableKind}; /// Arranges a function signature and a generated circuit's return witnesses into a /// `noirc_abi::Abi`. @@ -21,7 +27,7 @@ pub(super) fn gen_abi( context: &Context, func_id: &FuncId, return_visibility: Visibility, - error_types: BTreeMap, + error_types: BTreeMap, ) -> Abi { let (parameters, return_type) = compute_function_abi(context, func_id); let return_type = return_type.map(|typ| AbiReturnType { @@ -30,23 +36,37 @@ pub(super) fn gen_abi( }); let error_types = error_types .into_iter() - .map(|(selector, typ)| (selector, build_abi_error_type(context, &typ))) + .map(|(selector, typ)| (selector, build_abi_error_type(context, typ))) .collect(); Abi { parameters, return_type, error_types } } -fn build_abi_error_type(context: &Context, typ: &Type) -> AbiErrorType { +// Get the Span of the root crate's main function, or else a dummy span if that fails +fn get_main_function_span(context: &Context) -> Span { + if let Some(func_id) = context.get_main_function(context.root_crate_id()) { + context.function_meta(&func_id).location.span + } else { + Span::default() + } +} + +fn build_abi_error_type(context: &Context, typ: ErrorType) -> AbiErrorType { match typ { - Type::FmtString(len, item_types) => { - let length = len.evaluate_to_u32().expect("Cannot evaluate fmt length"); - let Type::Tuple(item_types) = item_types.as_ref() else { - unreachable!("FmtString items must be a tuple") - }; - let item_types = - item_types.iter().map(|typ| abi_type_from_hir_type(context, typ)).collect(); - AbiErrorType::FmtString { length, item_types } + ErrorType::Dynamic(typ) => { + if let Type::FmtString(len, item_types) = typ { + let span = get_main_function_span(context); + let length = len.evaluate_to_u32(span).expect("Cannot evaluate fmt length"); + let Type::Tuple(item_types) = item_types.as_ref() else { + unreachable!("FmtString items must be a tuple") + }; + let item_types = + item_types.iter().map(|typ| abi_type_from_hir_type(context, typ)).collect(); + AbiErrorType::FmtString { length, item_types } + } else { + AbiErrorType::Custom(abi_type_from_hir_type(context, &typ)) + } } - _ => AbiErrorType::Custom(abi_type_from_hir_type(context, typ)), + ErrorType::String(string) => AbiErrorType::String { string }, } } @@ -54,8 +74,9 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType { match typ { Type::FieldElement => AbiType::Field, Type::Array(size, typ) => { + let span = get_main_function_span(context); let length = size - .evaluate_to_u32() + .evaluate_to_u32(span) .expect("Cannot have variable sized arrays as a parameter to main"); let typ = typ.as_ref(); AbiType::Array { length, typ: Box::new(abi_type_from_hir_type(context, typ)) } @@ -68,17 +89,23 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType { AbiType::Integer { sign, width: (*bit_width).into() } } - Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) - | Type::TypeVariable(binding, TypeVariableKind::Integer) => match &*binding.borrow() { - TypeBinding::Bound(typ) => abi_type_from_hir_type(context, typ), - TypeBinding::Unbound(_) => { - abi_type_from_hir_type(context, &Type::default_int_or_field_type()) + Type::TypeVariable(binding) => { + if binding.is_integer() || binding.is_integer_or_field() { + match &*binding.borrow() { + TypeBinding::Bound(typ) => abi_type_from_hir_type(context, typ), + TypeBinding::Unbound(_id, _kind) => { + abi_type_from_hir_type(context, &Type::default_int_or_field_type()) + } + } + } else { + unreachable!("{typ} cannot be used in the abi") } - }, + } Type::Bool => AbiType::Boolean, Type::String(size) => { + let span = get_main_function_span(context); let size = size - .evaluate_to_u32() + .evaluate_to_u32(span) .expect("Cannot have variable sized strings as a parameter to main"); AbiType::String { length: size } } @@ -93,6 +120,7 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType { AbiType::Struct { fields, path } } Type::Alias(def, args) => abi_type_from_hir_type(context, &def.borrow().get_type(args)), + Type::CheckedCast { to, .. } => abi_type_from_hir_type(context, to), Type::Tuple(fields) => { let fields = vecmap(fields, |typ| abi_type_from_hir_type(context, typ)); AbiType::Tuple { fields } @@ -102,7 +130,6 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType { | Type::Constant(..) | Type::InfixExpr(..) | Type::TraitAsType(..) - | Type::TypeVariable(_, _) | Type::NamedGeneric(..) | Type::Forall(..) | Type::Quoted(_) diff --git a/compiler/noirc_driver/src/debug.rs b/compiler/noirc_driver/src/debug.rs index f5eaede89b2..6044e6c0e65 100644 --- a/compiler/noirc_driver/src/debug.rs +++ b/compiler/noirc_driver/src/debug.rs @@ -8,7 +8,7 @@ use std::{ /// For a given file, we store the source code and the path to the file /// so consumers of the debug artifact can reconstruct the original source code structure. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, Hash)] pub struct DebugFile { pub source: String, pub path: PathBuf, diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 1d69e435738..9318e4d2b5c 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -5,14 +5,15 @@ use abi_gen::{abi_type_from_hir_type, value_from_hir_expression}; use acvm::acir::circuit::ExpressionWidth; +use acvm::compiler::MIN_EXPRESSION_WIDTH; use clap::Args; use fm::{FileId, FileManager}; use iter_extended::vecmap; use noirc_abi::{AbiParameter, AbiType, AbiValue}; -use noirc_errors::{CustomDiagnostic, FileDiagnostic}; +use noirc_errors::{CustomDiagnostic, DiagnosticKind, FileDiagnostic}; use noirc_evaluator::create_program; use noirc_evaluator::errors::RuntimeError; -use noirc_evaluator::ssa::SsaProgramArtifact; +use noirc_evaluator::ssa::{SsaLogging, SsaProgramArtifact}; use noirc_frontend::debug::build_debug_crate_file; use noirc_frontend::hir::def_map::{Contract, CrateDefMap}; use noirc_frontend::hir::Context; @@ -69,6 +70,11 @@ pub struct CompileOptions { #[arg(long, hide = true)] pub show_ssa: bool, + /// Only show SSA passes whose name contains the provided string. + /// This setting takes precedence over `show_ssa` if it's not empty. + #[arg(long, hide = true)] + pub show_ssa_pass_name: Option, + /// Emit the unoptimized SSA IR to file. /// The IR will be dumped into the workspace target directory, /// under `[compiled-package].ssa.json`. @@ -124,6 +130,26 @@ pub struct CompileOptions { /// This check should always be run on production code. #[arg(long)] pub skip_underconstrained_check: bool, + + /// Flag to turn off the compiler check for missing Brillig call constrains. + /// Warning: This can improve compilation speed but can also lead to correctness errors. + /// This check should always be run on production code. + #[arg(long)] + pub skip_brillig_constraints_check: bool, + + /// Setting to decide on an inlining strategy for Brillig functions. + /// A more aggressive inliner should generate larger programs but more optimized + /// A less aggressive inliner should generate smaller programs + #[arg(long, hide = true, allow_hyphen_values = true, default_value_t = i64::MAX)] + pub inliner_aggressiveness: i64, + + /// Setting the maximum acceptable increase in Brillig bytecode size due to + /// unrolling small loops. When left empty, any change is accepted as long + /// as it required fewer SSA instructions. + /// A higher value results in fewer jumps but a larger program. + /// A lower value keeps the original program if it was smaller, even if it has more jumps. + #[arg(long, hide = true, allow_hyphen_values = true)] + pub max_bytecode_increase_percent: Option, } pub fn parse_expression_width(input: &str) -> Result { @@ -134,7 +160,11 @@ pub fn parse_expression_width(input: &str) -> Result Ok(ExpressionWidth::Unbounded), - _ => Ok(ExpressionWidth::Bounded { width }), + w if w >= MIN_EXPRESSION_WIDTH => Ok(ExpressionWidth::Bounded { width }), + _ => Err(Error::new( + ErrorKind::InvalidInput, + format!("has to be 0 or at least {MIN_EXPRESSION_WIDTH}"), + )), } } @@ -271,13 +301,12 @@ pub fn add_dep( /// /// This returns a (possibly empty) vector of any warnings found on success. /// On error, this returns a non-empty vector of warnings and error messages, with at least one error. -#[tracing::instrument(level = "trace", skip(context))] +#[tracing::instrument(level = "trace", skip_all)] pub fn check_crate( context: &mut Context, crate_id: CrateId, options: &CompileOptions, ) -> CompilationResult<()> { - let mut errors = vec![]; let error_on_unused_imports = true; let diagnostics = CrateDefMap::collect_defs( crate_id, @@ -285,15 +314,22 @@ pub fn check_crate( options.debug_comptime_in_file.as_deref(), error_on_unused_imports, ); - errors.extend(diagnostics.into_iter().map(|(error, file_id)| { - let diagnostic = CustomDiagnostic::from(&error); - diagnostic.in_file(file_id) - })); + let warnings_and_errors: Vec = diagnostics + .into_iter() + .map(|(error, file_id)| { + let diagnostic = CustomDiagnostic::from(&error); + diagnostic.in_file(file_id) + }) + .filter(|diagnostic| { + // We filter out any warnings if they're going to be ignored later on to free up memory. + !options.silence_warnings || diagnostic.diagnostic.kind != DiagnosticKind::Warning + }) + .collect(); - if has_errors(&errors, options.deny_warnings) { - Err(errors) + if has_errors(&warnings_and_errors, options.deny_warnings) { + Err(warnings_and_errors) } else { - Ok(((), errors)) + Ok(((), warnings_and_errors)) } } @@ -310,6 +346,8 @@ pub fn compute_function_abi( /// /// On success this returns the compiled program alongside any warnings that were found. /// On error this returns the non-empty list of warnings and errors. +/// +/// See [compile_no_check] for further information about the use of `cached_program`. pub fn compile_main( context: &mut Context, crate_id: CrateId, @@ -444,14 +482,11 @@ fn compile_contract_inner( .attributes .secondary .iter() - .filter_map(|attr| { - if let SecondaryAttribute::Custom(attribute) = attr { - Some(&attribute.contents) - } else { - None - } + .filter_map(|attr| match attr { + SecondaryAttribute::Tag(attribute) => Some(attribute.contents.clone()), + SecondaryAttribute::Meta(attribute) => Some(attribute.to_string()), + _ => None, }) - .cloned() .collect(); functions.push(ContractFunction { @@ -534,6 +569,15 @@ pub const DEFAULT_EXPRESSION_WIDTH: ExpressionWidth = ExpressionWidth::Bounded { /// Compile the current crate using `main_function` as the entrypoint. /// /// This function assumes [`check_crate`] is called beforehand. +/// +/// If the program is not returned from cache, it is backend-agnostic and must go through a transformation +/// pass before usage in proof generation; if it's returned from cache these transformations might have +/// already been applied. +/// +/// The transformations are _not_ covered by the check that decides whether we can use the cached artifact. +/// That comparison is based on on [CompiledProgram::hash] which is a persisted version of the hash of the input +/// [`ast::Program`][noirc_frontend::monomorphization::ast::Program], whereas the output [`circuit::Program`][acir::circuit::Program] +/// contains the final optimized ACIR opcodes, including the transformation done after this compilation. #[tracing::instrument(level = "trace", skip_all, fields(function_name = context.function_name(&main_function)))] pub fn compile_no_check( context: &mut Context, @@ -548,8 +592,6 @@ pub fn compile_no_check( monomorphize(main_function, &mut context.def_interner)? }; - let hash = fxhash::hash64(&program); - let hashes_match = cached_program.as_ref().map_or(false, |program| program.hash == hash); if options.show_monomorphized { println!("{program}"); } @@ -563,13 +605,28 @@ pub fn compile_no_check( || options.show_ssa || options.emit_ssa; - if !force_compile && hashes_match { - info!("Program matches existing artifact, returning early"); - return Ok(cached_program.expect("cache must exist for hashes to match")); + // Hash the AST program, which is going to be used to fingerprint the compilation artifact. + let hash = fxhash::hash64(&program); + + if let Some(cached_program) = cached_program { + if !force_compile && cached_program.hash == hash { + info!("Program matches existing artifact, returning early"); + return Ok(cached_program); + } } + let return_visibility = program.return_visibility; let ssa_evaluator_options = noirc_evaluator::ssa::SsaEvaluatorOptions { - enable_ssa_logging: options.show_ssa, + ssa_logging: match &options.show_ssa_pass_name { + Some(string) => SsaLogging::Contains(string.clone()), + None => { + if options.show_ssa { + SsaLogging::All + } else { + SsaLogging::None + } + } + }, enable_brillig_logging: options.show_brillig, force_brillig_output: options.force_brillig, print_codegen_timings: options.benchmark_codegen, @@ -580,6 +637,9 @@ pub fn compile_no_check( }, emit_ssa: if options.emit_ssa { Some(context.package_build_path.clone()) } else { None }, skip_underconstrained_check: options.skip_underconstrained_check, + skip_brillig_constraints_check: options.skip_brillig_constraints_check, + inliner_aggressiveness: options.inliner_aggressiveness, + max_bytecode_increase_percent: options.max_bytecode_increase_percent, }; let SsaProgramArtifact { program, debug, warnings, names, brillig_names, error_types, .. } = diff --git a/compiler/noirc_driver/src/program.rs b/compiler/noirc_driver/src/program.rs index 88460482928..4b4d6662e8e 100644 --- a/compiler/noirc_driver/src/program.rs +++ b/compiler/noirc_driver/src/program.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use super::debug::DebugFile; -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, Hash)] pub struct CompiledProgram { pub noir_version: String, /// Hash of the [`Program`][noirc_frontend::monomorphization::ast::Program] from which this [`CompiledProgram`] diff --git a/compiler/noirc_errors/Cargo.toml b/compiler/noirc_errors/Cargo.toml index 61b274c605f..a6927eb647a 100644 --- a/compiler/noirc_errors/Cargo.toml +++ b/compiler/noirc_errors/Cargo.toml @@ -16,7 +16,6 @@ acvm.workspace = true codespan-reporting.workspace = true codespan.workspace = true fm.workspace = true -chumsky.workspace = true noirc_printable_type.workspace = true serde.workspace = true serde_with = "3.2.0" diff --git a/compiler/noirc_errors/src/debug_info.rs b/compiler/noirc_errors/src/debug_info.rs index b480d20fde4..a5e12b37712 100644 --- a/compiler/noirc_errors/src/debug_info.rs +++ b/compiler/noirc_errors/src/debug_info.rs @@ -12,7 +12,6 @@ use serde::Serializer; use serde_with::serde_as; use serde_with::DisplayFromStr; use std::collections::BTreeMap; -use std::collections::HashMap; use std::io::Read; use std::io::Write; use std::mem; @@ -48,6 +47,9 @@ pub type DebugVariables = BTreeMap; pub type DebugFunctions = BTreeMap; pub type DebugTypes = BTreeMap; +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)] +pub struct ProcedureDebugId(pub u32); + #[derive(Default, Debug, Clone, Deserialize, Serialize)] pub struct ProgramDebugInfo { pub debug_infos: Vec, @@ -92,7 +94,7 @@ impl ProgramDebugInfo { } #[serde_as] -#[derive(Default, Debug, Clone, Deserialize, Serialize)] +#[derive(Default, Debug, Clone, Deserialize, Serialize, Hash)] pub struct DebugInfo { /// Map opcode index of an ACIR circuit into the source code location /// Serde does not support mapping keys being enums for json, so we indicate @@ -104,14 +106,9 @@ pub struct DebugInfo { pub variables: DebugVariables, pub functions: DebugFunctions, pub types: DebugTypes, -} - -/// Holds OpCodes Counts for Acir and Brillig Opcodes -/// To be printed with `nargo info --profile-info` -#[derive(Default, Debug, Serialize, Deserialize, Clone)] -pub struct OpCodesCount { - pub acir_size: usize, - pub brillig_size: usize, + /// This a map per brillig function representing the range of opcodes where a procedure is activated. + pub brillig_procedure_locs: + BTreeMap>, } impl DebugInfo { @@ -124,8 +121,12 @@ impl DebugInfo { variables: DebugVariables, functions: DebugFunctions, types: DebugTypes, + brillig_procedure_locs: BTreeMap< + BrilligFunctionId, + BTreeMap, + >, ) -> Self { - Self { locations, brillig_locations, variables, functions, types } + Self { locations, brillig_locations, variables, functions, types, brillig_procedure_locs } } /// Updates the locations map when the [`Circuit`][acvm::acir::circuit::Circuit] is modified. @@ -147,38 +148,4 @@ impl DebugInfo { pub fn opcode_location(&self, loc: &OpcodeLocation) -> Option> { self.locations.get(loc).cloned() } - - pub fn count_span_opcodes(&self) -> HashMap { - let mut accumulator: HashMap> = HashMap::new(); - - for (opcode_location, locations) in self.locations.iter() { - for location in locations.iter() { - let opcodes = accumulator.entry(*location).or_default(); - opcodes.push(opcode_location); - } - } - - let counted_opcodes = accumulator - .iter() - .map(|(location, opcodes)| { - let acir_opcodes: Vec<_> = opcodes - .iter() - .filter(|opcode_location| matches!(opcode_location, OpcodeLocation::Acir(_))) - .collect(); - let brillig_opcodes: Vec<_> = opcodes - .iter() - .filter(|opcode_location| { - matches!(opcode_location, OpcodeLocation::Brillig { .. }) - }) - .collect(); - let opcodes_count = OpCodesCount { - acir_size: acir_opcodes.len(), - brillig_size: brillig_opcodes.len(), - }; - (*location, opcodes_count) - }) - .collect(); - - counted_opcodes - } } diff --git a/compiler/noirc_errors/src/position.rs b/compiler/noirc_errors/src/position.rs index 9b031f56ae2..c7a64c4f422 100644 --- a/compiler/noirc_errors/src/position.rs +++ b/compiler/noirc_errors/src/position.rs @@ -8,7 +8,7 @@ use std::{ pub type Position = u32; -#[derive(PartialOrd, Eq, Ord, Debug, Clone)] +#[derive(PartialOrd, Eq, Ord, Debug, Clone, Default)] pub struct Spanned { pub contents: T, span: Span, @@ -94,8 +94,10 @@ impl Span { self.start() <= other.start() && self.end() >= other.end() } + /// Returns `true` if any point of `self` intersects a point of `other`. + /// Adjacent spans are considered to intersect (so, for example, `0..1` intersects `1..3`). pub fn intersects(&self, other: &Span) -> bool { - self.end() > other.start() && self.start() < other.end() + self.end() >= other.start() && self.start() <= other.end() } pub fn is_smaller(&self, other: &Span) -> bool { @@ -121,26 +123,6 @@ impl From> for Span { } } -impl chumsky::Span for Span { - type Context = (); - - type Offset = u32; - - fn new(_context: Self::Context, range: Range) -> Self { - Span(ByteSpan::from(range)) - } - - fn context(&self) -> Self::Context {} - - fn start(&self) -> Self::Offset { - self.start() - } - - fn end(&self) -> Self::Offset { - self.end() - } -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] pub struct Location { pub span: Span, @@ -160,3 +142,37 @@ impl Location { self.file == other.file && self.span.contains(&other.span) } } + +#[cfg(test)] +mod tests { + use crate::Span; + + #[test] + fn test_intersects() { + assert!(Span::from(5..10).intersects(&Span::from(5..10))); + + assert!(Span::from(5..10).intersects(&Span::from(5..5))); + assert!(Span::from(5..5).intersects(&Span::from(5..10))); + + assert!(Span::from(10..10).intersects(&Span::from(5..10))); + assert!(Span::from(5..10).intersects(&Span::from(10..10))); + + assert!(Span::from(5..10).intersects(&Span::from(6..9))); + assert!(Span::from(6..9).intersects(&Span::from(5..10))); + + assert!(Span::from(5..10).intersects(&Span::from(4..11))); + assert!(Span::from(4..11).intersects(&Span::from(5..10))); + + assert!(Span::from(5..10).intersects(&Span::from(4..6))); + assert!(Span::from(4..6).intersects(&Span::from(5..10))); + + assert!(Span::from(5..10).intersects(&Span::from(9..11))); + assert!(Span::from(9..11).intersects(&Span::from(5..10))); + + assert!(!Span::from(5..10).intersects(&Span::from(3..4))); + assert!(!Span::from(3..4).intersects(&Span::from(5..10))); + + assert!(!Span::from(5..10).intersects(&Span::from(11..12))); + assert!(!Span::from(11..12).intersects(&Span::from(5..10))); + } +} diff --git a/compiler/noirc_errors/src/reporter.rs b/compiler/noirc_errors/src/reporter.rs index 76e308969b4..e57775d9a7f 100644 --- a/compiler/noirc_errors/src/reporter.rs +++ b/compiler/noirc_errors/src/reporter.rs @@ -10,7 +10,7 @@ use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; pub struct CustomDiagnostic { pub message: String, pub secondaries: Vec, - notes: Vec, + pub notes: Vec, pub kind: DiagnosticKind, pub deprecated: bool, pub unnecessary: bool, @@ -272,7 +272,7 @@ fn convert_diagnostic( diagnostic.with_message(&cd.message).with_labels(secondary_labels).with_notes(notes) } -fn stack_trace<'files>( +pub fn stack_trace<'files>( files: &'files impl Files<'files, FileId = fm::FileId>, call_stack: &[Location], ) -> String { diff --git a/compiler/noirc_evaluator/Cargo.toml b/compiler/noirc_evaluator/Cargo.toml index 1db6af2ae85..72fba8aadc2 100644 --- a/compiler/noirc_evaluator/Cargo.toml +++ b/compiler/noirc_evaluator/Cargo.toml @@ -31,7 +31,11 @@ cfg-if.workspace = true [dev-dependencies] proptest.workspace = true +similar-asserts.workspace = true +tracing-test = "0.2.5" +num-traits.workspace = true +test-case.workspace = true [features] bn254 = ["noirc_frontend/bn254"] -bls12_381= [] +bls12_381 = [] diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/acir/acir_variable.rs similarity index 95% rename from compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs rename to compiler/noirc_evaluator/src/acir/acir_variable.rs index b0f283eeaeb..9f2c649ee3e 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/acir/acir_variable.rs @@ -1,24 +1,18 @@ -use super::big_int::BigIntContext; -use super::generated_acir::{BrilligStdlibFunc, GeneratedAcir, PLACEHOLDER_BRILLIG_INDEX}; -use crate::brillig::brillig_gen::brillig_directive; -use crate::brillig::brillig_ir::artifact::GeneratedBrillig; -use crate::errors::{InternalBug, InternalError, RuntimeError, SsaReport}; -use crate::ssa::acir_gen::{AcirDynamicArray, AcirValue}; -use crate::ssa::ir::dfg::CallStack; -use crate::ssa::ir::types::Type as SsaType; -use crate::ssa::ir::{instruction::Endian, types::NumericType}; -use acvm::acir::circuit::brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}; -use acvm::acir::circuit::opcodes::{AcirFunctionId, BlockId, BlockType, MemOp}; -use acvm::acir::circuit::{AssertionPayload, ExpressionOrMemory, ExpressionWidth, Opcode}; -use acvm::brillig_vm::{MemoryValue, VMStatus, VM}; use acvm::{ - acir::AcirField, acir::{ brillig::Opcode as BrilligOpcode, - circuit::opcodes::FunctionInput, + circuit::{ + brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, + opcodes::{ + AcirFunctionId, BlockId, BlockType, ConstantOrWitnessEnum, FunctionInput, MemOp, + }, + AssertionPayload, ExpressionOrMemory, ExpressionWidth, Opcode, + }, native_types::{Expression, Witness}, - BlackBoxFunc, + AcirField, BlackBoxFunc, }, + brillig_vm::{MemoryValue, VMStatus, VM}, + BlackBoxFunctionSolver, }; use fxhash::FxHashMap as HashMap; use iter_extended::{try_vecmap, vecmap}; @@ -26,6 +20,16 @@ use num_bigint::BigUint; use std::cmp::Ordering; use std::{borrow::Cow, hash::Hash}; +use crate::brillig::brillig_ir::artifact::GeneratedBrillig; +use crate::errors::{InternalBug, InternalError, RuntimeError, SsaReport}; +use crate::ssa::ir::{ + dfg::CallStack, instruction::Endian, types::NumericType, types::Type as SsaType, +}; + +use super::big_int::BigIntContext; +use super::generated_acir::{BrilligStdlibFunc, GeneratedAcir, PLACEHOLDER_BRILLIG_INDEX}; +use super::{brillig_directive, AcirDynamicArray, AcirValue}; + #[derive(Clone, Debug, PartialEq, Eq, Hash)] /// High level Type descriptor for Variables. /// @@ -88,7 +92,7 @@ impl<'a> From<&'a SsaType> for AcirType { SsaType::Numeric(numeric_type) => AcirType::NumericType(*numeric_type), SsaType::Array(elements, size) => { let elements = elements.iter().map(|e| e.into()).collect(); - AcirType::Array(elements, *size) + AcirType::Array(elements, *size as usize) } _ => unreachable!("The type {value} cannot be represented in ACIR"), } @@ -105,7 +109,9 @@ impl From for AcirType { /// Context object which holds the relationship between /// `Variables`(AcirVar) and types such as `Expression` and `Witness` /// which are placed into ACIR. -pub(crate) struct AcirContext { +pub(crate) struct AcirContext> { + blackbox_solver: B, + /// Two-way map that links `AcirVar` to `AcirVarData`. /// /// The vars object is an instance of the `TwoWayMap`, which provides a bidirectional mapping between `AcirVar` and `AcirVarData`. @@ -130,7 +136,7 @@ pub(crate) struct AcirContext { pub(crate) warnings: Vec, } -impl AcirContext { +impl> AcirContext { pub(crate) fn set_expression_width(&mut self, expression_width: ExpressionWidth) { self.expression_width = expression_width; } @@ -572,7 +578,7 @@ impl AcirContext { let numeric_type = match typ { AcirType::NumericType(numeric_type) => numeric_type, AcirType::Array(_, _) => { - todo!("cannot divide arrays. This should have been caught by the frontend") + unreachable!("cannot divide arrays. This should have been caught by the frontend") } }; match numeric_type { @@ -1078,11 +1084,22 @@ impl AcirContext { &mut self, lhs: AcirVar, rhs: AcirVar, + typ: AcirType, bit_size: u32, predicate: AcirVar, ) -> Result { - let (_, remainder) = self.euclidean_division_var(lhs, rhs, bit_size, predicate)?; - Ok(remainder) + let numeric_type = match typ { + AcirType::NumericType(numeric_type) => numeric_type, + AcirType::Array(_, _) => { + unreachable!("cannot modulo arrays. This should have been caught by the frontend") + } + }; + + let (_, remainder_var) = match numeric_type { + NumericType::Signed { bit_size } => self.signed_division_var(lhs, rhs, bit_size)?, + _ => self.euclidean_division_var(lhs, rhs, bit_size, predicate)?, + }; + Ok(remainder_var) } /// Constrains the `AcirVar` variable to be of type `NumericType`. @@ -1106,10 +1123,10 @@ impl AcirContext { let witness = self.var_to_witness(witness_var)?; self.acir_ir.range_constraint(witness, *bit_size)?; if let Some(message) = message { - self.acir_ir.assertion_payloads.insert( - self.acir_ir.last_acir_opcode_location(), - AssertionPayload::StaticString(message.clone()), - ); + let payload = self.generate_assertion_message_payload(message.clone()); + self.acir_ir + .assertion_payloads + .insert(self.acir_ir.last_acir_opcode_location(), payload); } } NumericType::NativeField => { @@ -1284,31 +1301,6 @@ impl AcirContext { ) -> Result, RuntimeError> { // Separate out any arguments that should be constants let (constant_inputs, constant_outputs) = match name { - BlackBoxFunc::PedersenCommitment | BlackBoxFunc::PedersenHash => { - // The last argument of pedersen is the domain separator, which must be a constant - let domain_var = match inputs.pop() { - Some(domain_var) => domain_var.into_var()?, - None => { - return Err(RuntimeError::InternalError(InternalError::MissingArg { - name: "pedersen call".to_string(), - arg: "domain separator".to_string(), - call_stack: self.get_call_stack(), - })) - } - }; - - let domain_constant = match self.vars[&domain_var].as_constant() { - Some(domain_constant) => domain_constant, - None => { - return Err(RuntimeError::InternalError(InternalError::NotAConstant { - name: "domain separator".to_string(), - call_stack: self.get_call_stack(), - })) - } - }; - - (vec![*domain_constant], Vec::new()) - } BlackBoxFunc::Poseidon2Permutation => { // The last argument is the state length, which must be a constant let state_len = match inputs.pop() { @@ -1459,22 +1451,7 @@ impl AcirContext { } _ => (vec![], vec![]), }; - // Allow constant inputs for most blackbox - // EmbeddedCurveAdd needs to be fixed first in bb - // Poseidon2Permutation requires witness input - let allow_constant_inputs = matches!( - name, - BlackBoxFunc::MultiScalarMul - | BlackBoxFunc::Keccakf1600 - | BlackBoxFunc::Blake2s - | BlackBoxFunc::Blake3 - | BlackBoxFunc::AND - | BlackBoxFunc::XOR - | BlackBoxFunc::AES128Encrypt - | BlackBoxFunc::EmbeddedCurveAdd - ); - // Convert `AcirVar` to `FunctionInput` - let inputs = self.prepare_inputs_for_black_box_func_call(inputs, allow_constant_inputs)?; + let inputs = self.prepare_inputs_for_black_box_func(inputs, name)?; // Call Black box with `FunctionInput` let mut results = vecmap(&constant_outputs, |c| self.add_constant(*c)); let outputs = self.acir_ir.call_black_box( @@ -1496,6 +1473,34 @@ impl AcirContext { Ok(results) } + fn prepare_inputs_for_black_box_func( + &mut self, + inputs: Vec, + name: BlackBoxFunc, + ) -> Result>>, RuntimeError> { + // Allow constant inputs for most blackbox, but: + // - EmbeddedCurveAdd requires all-or-nothing constant inputs + // - Poseidon2Permutation requires witness input + let allow_constant_inputs = matches!( + name, + BlackBoxFunc::MultiScalarMul + | BlackBoxFunc::Keccakf1600 + | BlackBoxFunc::Blake2s + | BlackBoxFunc::Blake3 + | BlackBoxFunc::AND + | BlackBoxFunc::XOR + | BlackBoxFunc::AES128Encrypt + | BlackBoxFunc::EmbeddedCurveAdd + ); + // Convert `AcirVar` to `FunctionInput` + let mut inputs = + self.prepare_inputs_for_black_box_func_call(inputs, allow_constant_inputs)?; + if name == BlackBoxFunc::EmbeddedCurveAdd { + inputs = self.all_or_nothing_for_ec_add(inputs)?; + } + Ok(inputs) + } + /// Black box function calls expect their inputs to be in a specific data structure (FunctionInput). /// /// This function will convert `AcirVar` into `FunctionInput` for a blackbox function call. @@ -1536,6 +1541,41 @@ impl AcirContext { Ok(witnesses) } + /// EcAdd has 6 inputs representing the two points to add + /// Each point must be either all constant, or all witnesses + fn all_or_nothing_for_ec_add( + &mut self, + inputs: Vec>>, + ) -> Result>>, RuntimeError> { + let mut has_constant = false; + let mut has_witness = false; + let mut result = inputs.clone(); + for (i, input) in inputs.iter().enumerate() { + if input[0].is_constant() { + has_constant = true; + } else { + has_witness = true; + } + if i % 3 == 2 { + if has_constant && has_witness { + // Convert the constants to witness if mixed constant and witness, + for j in i - 2..i + 1 { + if let ConstantOrWitnessEnum::Constant(constant) = inputs[j][0].input() { + let constant = self.add_constant(constant); + let witness_var = self.get_or_create_witness_var(constant)?; + let witness = self.var_to_witness(witness_var)?; + result[j] = + vec![FunctionInput::witness(witness, inputs[j][0].num_bits())]; + } + } + } + has_constant = false; + has_witness = false; + } + } + Ok(result) + } + /// Returns a vector of `AcirVar`s constrained to be the decomposition of the given input /// over given radix. /// @@ -1733,8 +1773,8 @@ impl AcirContext { brillig_stdlib_func, ); - fn range_constraint_value( - context: &mut AcirContext, + fn range_constraint_value>( + context: &mut AcirContext, value: &AcirValue, ) -> Result<(), RuntimeError> { match value { @@ -1853,7 +1893,7 @@ impl AcirContext { inputs: &[BrilligInputs], outputs_types: &[AcirType], ) -> Option> { - let mut memory = (execute_brillig(code, inputs)?).into_iter(); + let mut memory = (execute_brillig(code, &self.blackbox_solver, inputs)?).into_iter(); let outputs_var = vecmap(outputs_types.iter(), |output| match output { AcirType::NumericType(_) => { @@ -2043,6 +2083,13 @@ impl AcirContext { self.acir_ir.push_opcode(Opcode::Call { id, inputs, outputs, predicate }); Ok(results) } + + pub(crate) fn generate_assertion_message_payload( + &mut self, + message: String, + ) -> AssertionPayload { + self.acir_ir.generate_assertion_message_payload(message) + } } /// Enum representing the possible values that a @@ -2139,8 +2186,9 @@ pub(crate) struct AcirVar(usize); /// Returns the finished state of the Brillig VM if execution can complete. /// /// Returns `None` if complete execution of the Brillig bytecode is not possible. -fn execute_brillig( +fn execute_brillig>( code: &[BrilligOpcode], + blackbox_solver: &B, inputs: &[BrilligInputs], ) -> Option>> { // Set input values @@ -2166,11 +2214,8 @@ fn execute_brillig( } // Instantiate a Brillig VM given the solved input registers and memory, along with the Brillig bytecode. - // - // We pass a stubbed solver here as a concrete solver implies a field choice which conflicts with this function - // being generic. - let solver = acvm::blackbox_solver::StubbedBlackBoxSolver; - let mut vm = VM::new(calldata, code, Vec::new(), &solver); + let profiling_active = false; + let mut vm = VM::new(calldata, code, Vec::new(), blackbox_solver, profiling_active); // Run the Brillig VM on these inputs, bytecode, etc! let vm_status = vm.process_opcodes(); diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs b/compiler/noirc_evaluator/src/acir/big_int.rs similarity index 100% rename from compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs rename to compiler/noirc_evaluator/src/acir/big_int.rs diff --git a/compiler/noirc_evaluator/src/acir/brillig_directive.rs b/compiler/noirc_evaluator/src/acir/brillig_directive.rs new file mode 100644 index 00000000000..89fc7f1eda5 --- /dev/null +++ b/compiler/noirc_evaluator/src/acir/brillig_directive.rs @@ -0,0 +1,276 @@ +use acvm::acir::{ + brillig::{ + BinaryFieldOp, BinaryIntOp, BitSize, HeapVector, IntegerBitSize, MemoryAddress, + Opcode as BrilligOpcode, + }, + AcirField, +}; + +use crate::brillig::brillig_ir::artifact::GeneratedBrillig; + +/// Generates brillig bytecode which computes the inverse of its input if not null, and zero else. +pub(crate) fn directive_invert() -> GeneratedBrillig { + // We generate the following code: + // fn invert(x : Field) -> Field { + // 1/ x + // } + + // The input argument, ie the value that will be inverted. + // We store the result in this register too. + let input = MemoryAddress::direct(0); + let one_const = MemoryAddress::direct(1); + let zero_const = MemoryAddress::direct(2); + let input_is_zero = MemoryAddress::direct(3); + let zero_usize = MemoryAddress::direct(20); + let one_usize = MemoryAddress::direct(21); + // Location of the stop opcode + let stop_location = 8; + + GeneratedBrillig { + byte_code: vec![ + BrilligOpcode::Const { + destination: one_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: F::from(1_usize), + }, + BrilligOpcode::Const { + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: F::from(0_usize), + }, + BrilligOpcode::CalldataCopy { + destination_address: input, + size_address: one_usize, + offset_address: zero_usize, + }, + // Put value zero in register (2) + BrilligOpcode::Const { + destination: zero_const, + value: F::from(0_usize), + bit_size: BitSize::Field, + }, + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Equals, + lhs: input, + rhs: zero_const, + destination: input_is_zero, + }, + // If the input is zero, then we jump to the stop opcode + BrilligOpcode::JumpIf { condition: input_is_zero, location: stop_location }, + // Put value one in register (1) + BrilligOpcode::Const { + destination: one_const, + value: F::one(), + bit_size: BitSize::Field, + }, + // Divide 1 by the input, and set the result of the division into register (0) + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Div, + lhs: one_const, + rhs: input, + destination: input, + }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: one_usize }, + }, + ], + name: "directive_invert".to_string(), + ..Default::default() + } +} + +/// Generates brillig bytecode which computes `a / b` and returns the quotient and remainder. +/// +/// This is equivalent to the Noir (pseudo)code +/// +/// ```text +/// fn quotient(a: T, b: T) -> (T,T) { +/// (a/b, a-a/b*b) +/// } +/// ``` +pub(crate) fn directive_quotient() -> GeneratedBrillig { + // `a` is (0) (i.e register index 0) + // `b` is (1) + + GeneratedBrillig { + byte_code: vec![ + BrilligOpcode::Const { + destination: MemoryAddress::direct(10), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: F::from(2_usize), + }, + BrilligOpcode::Const { + destination: MemoryAddress::direct(11), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: F::from(0_usize), + }, + BrilligOpcode::CalldataCopy { + destination_address: MemoryAddress::direct(0), + size_address: MemoryAddress::direct(10), + offset_address: MemoryAddress::direct(11), + }, + // No cast, since calldata is typed as field by default + //q = a/b is set into register (2) + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::IntegerDiv, // We want integer division, not field division! + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), + }, + //(1)= q*b + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Mul, + lhs: MemoryAddress::direct(2), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(1), + }, + //(1) = a-q*b + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Sub, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(1), + }, + //(0) = q + BrilligOpcode::Mov { + destination: MemoryAddress::direct(0), + source: MemoryAddress::direct(2), + }, + BrilligOpcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(11), + size: MemoryAddress::direct(10), + }, + }, + ], + name: "directive_integer_quotient".to_string(), + ..Default::default() + } +} + +/// Generates brillig bytecode which performs a radix-base decomposition of `a` +/// The brillig inputs are 'a', the numbers of limbs and the radix +pub(crate) fn directive_to_radix() -> GeneratedBrillig { + let memory_adr_int_size = IntegerBitSize::U32; + let memory_adr_size = BitSize::Integer(memory_adr_int_size); + + // (0) is the input field `a` to decompose + // (1) contains the number of limbs (second input) + let limbs_nb = MemoryAddress::direct(1); + // (2) contains the radix (third input) + let radix = MemoryAddress::direct(2); + // (3) and (4) are intermediate registers + // (5,6,7) are constants: 0,1,3 + let zero = MemoryAddress::direct(5); + let one = MemoryAddress::direct(6); + let three = MemoryAddress::direct(7); + // (7) is the iteration bound, it is the same register as three because the latter is only used at the start + let bound = MemoryAddress::direct(7); + // (8) is the register for storing the loop condition + let cond = MemoryAddress::direct(8); + // (9) is the pointer to the result array + let result_pointer = MemoryAddress::direct(9); + // address of the result array + let result_base_adr = 10_usize; + + let result_vector = HeapVector { pointer: result_pointer, size: limbs_nb }; + + let byte_code = vec![ + // Initialize registers + // Constants + // Zero + BrilligOpcode::Const { destination: zero, bit_size: memory_adr_size, value: F::zero() }, + // One + BrilligOpcode::Const { + destination: one, + bit_size: memory_adr_size, + value: F::from(1_usize), + }, + // Three + BrilligOpcode::Const { + destination: three, + bit_size: memory_adr_size, + value: F::from(3_usize), + }, + // Brillig Inputs + BrilligOpcode::CalldataCopy { + destination_address: MemoryAddress::direct(0), + size_address: three, + offset_address: zero, + }, + // The number of limbs needs to be an integer + BrilligOpcode::Cast { destination: limbs_nb, source: limbs_nb, bit_size: memory_adr_size }, + // Result_pointer starts at the base address + BrilligOpcode::Const { + destination: result_pointer, + bit_size: memory_adr_size, + value: F::from(result_base_adr), + }, + // Loop bound + BrilligOpcode::BinaryIntOp { + destination: bound, + op: BinaryIntOp::Add, + bit_size: memory_adr_int_size, + lhs: result_pointer, + rhs: limbs_nb, + }, + // loop label: (3) = a / radix (integer division) + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::IntegerDiv, + lhs: MemoryAddress::direct(0), + rhs: radix, + destination: MemoryAddress::direct(3), + }, + //(4) = (3)*256 + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Mul, + lhs: MemoryAddress::direct(3), + rhs: radix, + destination: MemoryAddress::direct(4), + }, + //(4) = a-(3)*256 (remainder) + BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Sub, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(4), + destination: MemoryAddress::direct(4), + }, + // Store the remainder in the result array + BrilligOpcode::Store { + destination_pointer: result_pointer, + source: MemoryAddress::direct(4), + }, + // Increment the result pointer + BrilligOpcode::BinaryIntOp { + op: BinaryIntOp::Add, + lhs: result_pointer, + rhs: one, + destination: result_pointer, + bit_size: memory_adr_int_size, + }, + //a := quotient + BrilligOpcode::Mov { + destination: MemoryAddress::direct(0), + source: MemoryAddress::direct(3), + }, + // loop condition + BrilligOpcode::BinaryIntOp { + op: BinaryIntOp::LessThan, + lhs: result_pointer, + rhs: bound, + destination: cond, + bit_size: memory_adr_int_size, + }, + // loop back + BrilligOpcode::JumpIf { condition: cond, location: 7 }, + // reset result pointer to the start of the array + BrilligOpcode::Const { + destination: result_pointer, + bit_size: memory_adr_size, + value: F::from(result_base_adr), + }, + BrilligOpcode::Stop { return_data: result_vector }, + ]; + + GeneratedBrillig { byte_code, name: "directive_to_radix".to_string(), ..Default::default() } +} diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/compiler/noirc_evaluator/src/acir/generated_acir.rs similarity index 88% rename from compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs rename to compiler/noirc_evaluator/src/acir/generated_acir.rs index 21d4dfb60b8..3b29c0319ab 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/compiler/noirc_evaluator/src/acir/generated_acir.rs @@ -1,26 +1,27 @@ //! `GeneratedAcir` is constructed as part of the `acir_gen` pass to accumulate all of the ACIR //! program as it is being converted from SSA form. -use std::{collections::BTreeMap, u32}; +use std::collections::BTreeMap; -use crate::{ - brillig::{brillig_gen::brillig_directive, brillig_ir::artifact::GeneratedBrillig}, - errors::{InternalError, RuntimeError, SsaReport}, - ssa::ir::dfg::CallStack, -}; use acvm::acir::{ circuit::{ brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, opcodes::{BlackBoxFuncCall, FunctionInput, Opcode as AcirOpcode}, - AssertionPayload, BrilligOpcodeLocation, OpcodeLocation, + AssertionPayload, BrilligOpcodeLocation, ErrorSelector, OpcodeLocation, }, - native_types::Witness, - BlackBoxFunc, + native_types::{Expression, Witness}, + AcirField, BlackBoxFunc, }; -use acvm::{ - acir::AcirField, - acir::{circuit::directives::Directive, native_types::Expression}, + +use super::brillig_directive; +use crate::{ + brillig::brillig_ir::artifact::GeneratedBrillig, + errors::{InternalError, RuntimeError, SsaReport}, + ssa::ir::dfg::CallStack, + ErrorType, }; + use iter_extended::vecmap; +use noirc_errors::debug_info::ProcedureDebugId; use num_bigint::BigUint; /// Brillig calls such as for the Brillig std lib are resolved only after code generation is finished. @@ -62,6 +63,9 @@ pub(crate) struct GeneratedAcir { /// Correspondence between an opcode index and the error message associated with it. pub(crate) assertion_payloads: BTreeMap>, + /// Correspondence between error selectors and types associated with them. + pub(crate) error_types: BTreeMap, + pub(crate) warnings: Vec, /// Name for the corresponding entry point represented by this Acir-gen output. @@ -72,6 +76,11 @@ pub(crate) struct GeneratedAcir { /// As to avoid passing the ACIR gen shared context into each individual ACIR /// we can instead keep this map and resolve the Brillig calls at the end of code generation. pub(crate) brillig_stdlib_func_locations: BTreeMap, + + /// Brillig function id -> Brillig procedure locations map + /// This maps allows a profiler to determine which Brillig opcodes + /// originated from a reusable procedure. + pub(crate) brillig_procedure_locs: BTreeMap, } /// Correspondence between an opcode index (in opcodes) and the source code call stack which generated it @@ -79,10 +88,13 @@ pub(crate) type OpcodeToLocationsMap = BTreeMap; pub(crate) type BrilligOpcodeToLocationsMap = BTreeMap; +pub(crate) type BrilligProcedureRangeMap = BTreeMap; + #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] pub(crate) enum BrilligStdlibFunc { Inverse, Quotient, + ToLeBytes, } impl BrilligStdlibFunc { @@ -90,6 +102,7 @@ impl BrilligStdlibFunc { match self { BrilligStdlibFunc::Inverse => brillig_directive::directive_invert(), BrilligStdlibFunc::Quotient => brillig_directive::directive_quotient(), + BrilligStdlibFunc::ToLeBytes => brillig_directive::directive_to_radix(), } } } @@ -144,7 +157,7 @@ impl GeneratedAcir { /// This means you cannot multiply an infinite amount of `Expression`s together. /// Once the `Expression` goes over degree-2, then it needs to be reduced to a `Witness` /// which has degree-1 in order to be able to continue the multiplication chain. - pub(crate) fn create_witness_for_expression(&mut self, expression: &Expression) -> Witness { + fn create_witness_for_expression(&mut self, expression: &Expression) -> Witness { let fresh_witness = self.next_witness_index(); // Create a constraint that sets them to be equal to each other @@ -212,29 +225,6 @@ impl GeneratedAcir { inputs: inputs[0].clone(), outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), }, - BlackBoxFunc::SchnorrVerify => { - BlackBoxFuncCall::SchnorrVerify { - public_key_x: inputs[0][0], - public_key_y: inputs[1][0], - // Schnorr signature is an r & s, 32 bytes each - signature: inputs[2] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - message: inputs[3].clone(), - output: outputs[0], - } - } - BlackBoxFunc::PedersenCommitment => BlackBoxFuncCall::PedersenCommitment { - inputs: inputs[0].clone(), - outputs: (outputs[0], outputs[1]), - domain_separator: constant_inputs[0].to_u128() as u32, - }, - BlackBoxFunc::PedersenHash => BlackBoxFuncCall::PedersenHash { - inputs: inputs[0].clone(), - output: outputs[0], - domain_separator: constant_inputs[0].to_u128() as u32, - }, BlackBoxFunc::EcdsaSecp256k1 => { BlackBoxFuncCall::EcdsaSecp256k1 { // 32 bytes for each public key co-ordinate @@ -294,9 +284,6 @@ impl GeneratedAcir { input2: Box::new([inputs[3][0], inputs[4][0], inputs[5][0]]), outputs: (outputs[0], outputs[1], outputs[2]), }, - BlackBoxFunc::Keccak256 => { - unreachable!("unexpected BlackBox {}", func_name.to_string()) - } BlackBoxFunc::Keccakf1600 => BlackBoxFuncCall::Keccakf1600 { inputs: inputs[0] .clone() @@ -381,12 +368,7 @@ impl GeneratedAcir { "ICE: Radix must be a power of 2" ); - let limb_witnesses = vecmap(0..limb_count, |_| self.next_witness_index()); - self.push_opcode(AcirOpcode::Directive(Directive::ToLeRadix { - a: input_expr.clone(), - b: limb_witnesses.clone(), - radix, - })); + let limb_witnesses = self.brillig_to_radix(input_expr, radix, limb_count); let mut composed_limbs = Expression::default(); @@ -407,6 +389,54 @@ impl GeneratedAcir { Ok(limb_witnesses) } + /// Adds brillig opcode for to_radix + /// + /// This code will decompose `expr` in a radix-base + /// and return `Witnesses` which may (or not, because it does not apply constraints) + /// be limbs resulting from the decomposition. + /// + /// Safety: It is the callers responsibility to ensure that the + /// resulting `Witnesses` are properly constrained. + pub(crate) fn brillig_to_radix( + &mut self, + expr: &Expression, + radix: u32, + limb_count: u32, + ) -> Vec { + // Create the witness for the result + let limb_witnesses = vecmap(0..limb_count, |_| self.next_witness_index()); + + // Get the decomposition brillig code + let le_bytes_code = brillig_directive::directive_to_radix(); + // Prepare the inputs/outputs + let limbs_nb = Expression { + mul_terms: Vec::new(), + linear_combinations: Vec::new(), + q_c: F::from(limb_count as u128), + }; + let radix_expr = Expression { + mul_terms: Vec::new(), + linear_combinations: Vec::new(), + q_c: F::from(radix as u128), + }; + let inputs = vec![ + BrilligInputs::Single(expr.clone()), + BrilligInputs::Single(limbs_nb), + BrilligInputs::Single(radix_expr), + ]; + let outputs = vec![BrilligOutputs::Array(limb_witnesses.clone())]; + + self.brillig_call( + None, + &le_bytes_code, + inputs, + outputs, + PLACEHOLDER_BRILLIG_INDEX, + Some(BrilligStdlibFunc::ToLeBytes), + ); + limb_witnesses + } + /// Adds an inversion brillig opcode. /// /// This code will invert `expr` without applying constraints @@ -475,7 +505,7 @@ impl GeneratedAcir { /// /// This equation however falls short when `t != 0` because then `t` /// may not be `1`. If `t` is non-zero, then `y` is also non-zero due to - /// `y == 1 - t` and the equation `y * t == 0` fails. + /// `y == 1 - t` and the equation `y * t == 0` fails. /// /// To fix, we introduce another free variable called `z` and apply the following /// constraint instead: `y == 1 - t * z`. @@ -485,7 +515,7 @@ impl GeneratedAcir { /// /// We now arrive at the conclusion that when `t == 0`, `y` is `1` and when /// `t != 0`, then `y` is `0`. - /// + /// /// Bringing it all together, We introduce two variables `y` and `z`, /// With the following equations: /// - `y == 1 - tz` (`z` is a value that is chosen to be the inverse of `t` by the prover) @@ -589,21 +619,22 @@ impl GeneratedAcir { return; } - // TODO(https://github.com/noir-lang/noir/issues/5792) - for (brillig_index, message) in generated_brillig.assert_messages.iter() { - self.assertion_payloads.insert( - OpcodeLocation::Brillig { - acir_index: self.opcodes.len() - 1, - brillig_index: *brillig_index, - }, - AssertionPayload::StaticString(message.clone()), - ); + for (error_selector, error_type) in generated_brillig.error_types.iter() { + self.record_error_type(*error_selector, error_type.clone()); } if inserted_func_before { return; } + for (procedure_id, (start_index, end_index)) in generated_brillig.procedure_locations.iter() + { + self.brillig_procedure_locs + .entry(brillig_function_index) + .or_default() + .insert(procedure_id.to_debug_id(), (*start_index, *end_index)); + } + for (brillig_index, call_stack) in generated_brillig.locations.iter() { self.brillig_locations .entry(brillig_function_index) @@ -632,6 +663,20 @@ impl GeneratedAcir { pub(crate) fn last_acir_opcode_location(&self) -> OpcodeLocation { OpcodeLocation::Acir(self.opcodes.len() - 1) } + + pub(crate) fn record_error_type(&mut self, selector: ErrorSelector, typ: ErrorType) { + self.error_types.insert(selector, typ); + } + + pub(crate) fn generate_assertion_message_payload( + &mut self, + message: String, + ) -> AssertionPayload { + let error_type = ErrorType::String(message); + let error_selector = error_type.selector(); + self.record_error_type(error_selector, error_type); + AssertionPayload { error_selector: error_selector.as_u64(), payload: Vec::new() } + } } /// This function will return the number of inputs that a blackbox function @@ -643,12 +688,7 @@ fn black_box_func_expected_input_size(name: BlackBoxFunc) -> Option { // All of the hash/cipher methods will take in a // variable number of inputs. - BlackBoxFunc::AES128Encrypt - | BlackBoxFunc::Keccak256 - | BlackBoxFunc::Blake2s - | BlackBoxFunc::Blake3 - | BlackBoxFunc::PedersenCommitment - | BlackBoxFunc::PedersenHash => None, + BlackBoxFunc::AES128Encrypt | BlackBoxFunc::Blake2s | BlackBoxFunc::Blake3 => None, BlackBoxFunc::Keccakf1600 => Some(25), // The permutation takes a fixed number of inputs, but the inputs length depends on the proving system implementation. @@ -662,9 +702,7 @@ fn black_box_func_expected_input_size(name: BlackBoxFunc) -> Option { // Signature verification algorithms will take in a variable // number of inputs, since the message/hashed-message can vary in size. - BlackBoxFunc::SchnorrVerify - | BlackBoxFunc::EcdsaSecp256k1 - | BlackBoxFunc::EcdsaSecp256r1 => None, + BlackBoxFunc::EcdsaSecp256k1 | BlackBoxFunc::EcdsaSecp256r1 => None, // Inputs for multi scalar multiplication is an arbitrary number of [point, scalar] pairs. BlackBoxFunc::MultiScalarMul => None, @@ -696,7 +734,7 @@ fn black_box_expected_output_size(name: BlackBoxFunc) -> Option { BlackBoxFunc::AND | BlackBoxFunc::XOR => Some(1), // 32 byte hash algorithms - BlackBoxFunc::Keccak256 | BlackBoxFunc::Blake2s | BlackBoxFunc::Blake3 => Some(32), + BlackBoxFunc::Blake2s | BlackBoxFunc::Blake3 => Some(32), BlackBoxFunc::Keccakf1600 => Some(25), // The permutation returns a fixed number of outputs, equals to the inputs length which depends on the proving system implementation. @@ -704,20 +742,12 @@ fn black_box_expected_output_size(name: BlackBoxFunc) -> Option { BlackBoxFunc::Sha256Compression => Some(8), - // Pedersen commitment returns a point - BlackBoxFunc::PedersenCommitment => Some(2), - - // Pedersen hash returns a field - BlackBoxFunc::PedersenHash => Some(1), - // Can only apply a range constraint to one // witness at a time. BlackBoxFunc::RANGE => Some(0), // Signature verification algorithms will return a boolean - BlackBoxFunc::SchnorrVerify - | BlackBoxFunc::EcdsaSecp256k1 - | BlackBoxFunc::EcdsaSecp256r1 => Some(1), + BlackBoxFunc::EcdsaSecp256k1 | BlackBoxFunc::EcdsaSecp256r1 => Some(1), // Output of operations over the embedded curve // will be 2 field elements representing the point. diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/acir/mod.rs similarity index 95% rename from compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs rename to compiler/noirc_evaluator/src/acir/mod.rs index 15d72c2ae74..769d0d80cc4 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/acir/mod.rs @@ -1,45 +1,57 @@ //! This file holds the pass to convert from Noir's SSA IR to ACIR. -mod acir_ir; +use fxhash::FxHashMap as HashMap; +use im::Vector; use std::collections::{BTreeMap, HashSet}; use std::fmt::Debug; -use self::acir_ir::acir_variable::{AcirContext, AcirType, AcirVar}; -use self::acir_ir::generated_acir::BrilligStdlibFunc; -use super::function_builder::data_bus::DataBus; -use super::ir::dfg::CallStack; -use super::ir::function::FunctionId; -use super::ir::instruction::{ConstrainError, ErrorType}; -use super::ir::printer::try_to_extract_string_from_error_payload; -use super::{ +use acvm::acir::{ + circuit::{ + brillig::{BrilligBytecode, BrilligFunctionId}, + opcodes::{AcirFunctionId, BlockType}, + AssertionPayload, ErrorSelector, ExpressionWidth, OpcodeLocation, + }, + native_types::Witness, + BlackBoxFunc, +}; +use acvm::{acir::circuit::opcodes::BlockId, acir::AcirField, FieldElement}; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use iter_extended::{try_vecmap, vecmap}; +use noirc_frontend::monomorphization::ast::InlineType; + +mod acir_variable; +mod big_int; +mod brillig_directive; +mod generated_acir; + +use crate::brillig::brillig_gen::gen_brillig_for; +use crate::brillig::{ + brillig_gen::brillig_fn::FunctionContext as BrilligFunctionContext, + brillig_ir::artifact::{BrilligParameter, GeneratedBrillig}, + Brillig, +}; +use crate::errors::{InternalError, InternalWarning, RuntimeError, SsaReport}; +use crate::ssa::ir::instruction::Hint; +use crate::ssa::{ + function_builder::data_bus::DataBus, ir::{ - dfg::DataFlowGraph, - function::{Function, RuntimeType}, + dfg::{CallStack, DataFlowGraph}, + function::{Function, FunctionId, RuntimeType}, instruction::{ - Binary, BinaryOp, Instruction, InstructionId, Intrinsic, TerminatorInstruction, + Binary, BinaryOp, ConstrainError, Instruction, InstructionId, Intrinsic, + TerminatorInstruction, }, map::Id, + printer::try_to_extract_string_from_error_payload, types::{NumericType, Type}, value::{Value, ValueId}, }, ssa_gen::Ssa, }; -use crate::brillig::brillig_ir::artifact::{BrilligParameter, GeneratedBrillig}; -use crate::brillig::brillig_ir::BrilligContext; -use crate::brillig::{brillig_gen::brillig_fn::FunctionContext as BrilligFunctionContext, Brillig}; -use crate::errors::{InternalError, InternalWarning, RuntimeError, SsaReport}; -pub(crate) use acir_ir::generated_acir::GeneratedAcir; -use acvm::acir::circuit::opcodes::{AcirFunctionId, BlockType}; -use noirc_frontend::monomorphization::ast::InlineType; - -use acvm::acir::circuit::brillig::{BrilligBytecode, BrilligFunctionId}; -use acvm::acir::circuit::{AssertionPayload, ErrorSelector, ExpressionWidth, OpcodeLocation}; -use acvm::acir::native_types::Witness; -use acvm::acir::BlackBoxFunc; -use acvm::{acir::circuit::opcodes::BlockId, acir::AcirField, FieldElement}; -use fxhash::FxHashMap as HashMap; -use im::Vector; -use iter_extended::{try_vecmap, vecmap}; +use acir_variable::{AcirContext, AcirType, AcirVar}; +use generated_acir::BrilligStdlibFunc; +pub(crate) use generated_acir::GeneratedAcir; +use noirc_frontend::hir_def::types::Type as HirType; #[derive(Default)] struct SharedContext { @@ -156,7 +168,7 @@ struct Context<'a> { current_side_effects_enabled_var: AcirVar, /// Manages and builds the `AcirVar`s to which the converted SSA values refer. - acir_context: AcirContext, + acir_context: AcirContext, /// Track initialized acir dynamic arrays /// @@ -283,7 +295,7 @@ pub(crate) type Artifacts = ( Vec>, Vec>, Vec, - BTreeMap, + BTreeMap, ); impl Ssa { @@ -296,6 +308,7 @@ impl Ssa { let mut acirs = Vec::new(); // TODO: can we parallelize this? let mut shared_context = SharedContext::default(); + for function in self.functions.values() { let context = Context::new(&mut shared_context, expression_width); if let Some(mut generated_acir) = @@ -377,7 +390,7 @@ impl<'a> Context<'a> { match function.runtime() { RuntimeType::Acir(inline_type) => { match inline_type { - InlineType::Inline => { + InlineType::Inline | InlineType::InlineAlways => { if function.id() != ssa.main_id { panic!("ACIR function should have been inlined earlier if not marked otherwise"); } @@ -390,7 +403,7 @@ impl<'a> Context<'a> { // We only want to convert entry point functions. This being `main` and those marked with `InlineType::Fold` Ok(Some(self.convert_acir_main(function, ssa, brillig)?)) } - RuntimeType::Brillig => { + RuntimeType::Brillig(_) => { if function.id() == ssa.main_id { Ok(Some(self.convert_brillig_main(function, brillig)?)) } else { @@ -504,7 +517,7 @@ impl<'a> Context<'a> { let outputs: Vec = vecmap(main_func.returns(), |result_id| dfg.type_of_value(*result_id).into()); - let code = self.gen_brillig_for(main_func, arguments.clone(), brillig)?; + let code = gen_brillig_for(main_func, arguments.clone(), brillig)?; // We specifically do not attempt execution of the brillig code being generated as this can result in it being // replaced with constraints on witnesses to the program outputs. @@ -559,7 +572,7 @@ impl<'a> Context<'a> { AcirValue::Array(_) => { let block_id = self.block_id(param_id); let len = if matches!(typ, Type::Array(_, _)) { - typ.flattened_size() + typ.flattened_size() as usize } else { return Err(InternalError::Unexpected { expected: "Block params should be an array".to_owned(), @@ -675,16 +688,19 @@ impl<'a> Context<'a> { let assert_payload = if let Some(error) = assert_message { match error { - ConstrainError::StaticString(string) => { - Some(AssertionPayload::StaticString(string.clone())) - } - ConstrainError::Dynamic(error_selector, values) => { + ConstrainError::StaticString(string) => Some( + self.acir_context.generate_assertion_message_payload(string.clone()), + ), + ConstrainError::Dynamic(error_selector, is_string_type, values) => { if let Some(constant_string) = try_to_extract_string_from_error_payload( - *error_selector, + *is_string_type, values, dfg, ) { - Some(AssertionPayload::StaticString(constant_string)) + Some( + self.acir_context + .generate_assertion_message_payload(constant_string), + ) } else { let acir_vars: Vec<_> = values .iter() @@ -694,10 +710,10 @@ impl<'a> Context<'a> { let expressions_or_memory = self.acir_context.vars_to_expressions_or_memory(&acir_vars)?; - Some(AssertionPayload::Dynamic( - error_selector.as_u64(), - expressions_or_memory, - )) + Some(AssertionPayload { + error_selector: error_selector.as_u64(), + payload: expressions_or_memory, + }) } } } @@ -766,6 +782,12 @@ impl<'a> Context<'a> { Instruction::IfElse { .. } => { unreachable!("IfElse instruction remaining in acir-gen") } + Instruction::MakeArray { elements, typ: _ } => { + let elements = elements.iter().map(|element| self.convert_value(*element, dfg)); + let value = AcirValue::Array(elements.collect()); + let result = dfg.instruction_results(instruction_id)[0]; + self.ssa_values.insert(result, value); + } } self.acir_context.set_call_stack(CallStack::new()); @@ -795,17 +817,17 @@ impl<'a> Context<'a> { let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); let output_count = result_ids .iter() - .map(|result_id| dfg.type_of_value(*result_id).flattened_size()) + .map(|result_id| { + dfg.type_of_value(*result_id).flattened_size() as usize + }) .sum(); - let Some(acir_function_id) = - ssa.entry_point_to_generated_index.get(id) - else { + let Some(acir_function_id) = ssa.get_entry_point_index(id) else { unreachable!("Expected an associated final index for call to acir function {id} with args {arguments:?}"); }; let output_vars = self.acir_context.call_acir_function( - AcirFunctionId(*acir_function_id), + AcirFunctionId(acir_function_id), inputs, output_count, self.current_side_effects_enabled_var, @@ -816,7 +838,7 @@ impl<'a> Context<'a> { self.handle_ssa_call_outputs(result_ids, output_values, dfg)?; } - RuntimeType::Brillig => { + RuntimeType::Brillig(_) => { // Check that we are not attempting to return a slice from // an unconstrained runtime to a constrained runtime for result_id in result_ids { @@ -855,8 +877,7 @@ impl<'a> Context<'a> { None, )? } else { - let code = - self.gen_brillig_for(func, arguments.clone(), brillig)?; + let code = gen_brillig_for(func, arguments.clone(), brillig)?; let generated_pointer = self.shared_context.new_generated_pointer(); let output_values = self.acir_context.brillig_call( @@ -928,7 +949,7 @@ impl<'a> Context<'a> { let block_id = self.block_id(&array_id); let array_typ = dfg.type_of_value(array_id); let len = if matches!(array_typ, Type::Array(_, _)) { - array_typ.flattened_size() + array_typ.flattened_size() as usize } else { Self::flattened_value_size(&output) }; @@ -976,38 +997,6 @@ impl<'a> Context<'a> { .collect() } - fn gen_brillig_for( - &self, - func: &Function, - arguments: Vec, - brillig: &Brillig, - ) -> Result, InternalError> { - // Create the entry point artifact - let mut entry_point = BrilligContext::new_entry_point_artifact( - arguments, - BrilligFunctionContext::return_values(func), - func.id(), - ); - entry_point.name = func.name().to_string(); - - // Link the entry point with all dependencies - while let Some(unresolved_fn_label) = entry_point.first_unresolved_function_call() { - let artifact = &brillig.find_by_label(unresolved_fn_label); - let artifact = match artifact { - Some(artifact) => artifact, - None => { - return Err(InternalError::General { - message: format!("Cannot find linked fn {unresolved_fn_label}"), - call_stack: CallStack::new(), - }) - } - }; - entry_point.link_with(artifact); - } - // Generate the final bytecode - Ok(entry_point.finish()) - } - /// Handles an ArrayGet or ArraySet instruction. /// To set an index of the array (and create a new array in doing so), pass Some(value) for /// store_value. To just retrieve an index of the array, pass None for store_value. @@ -1303,6 +1292,29 @@ impl<'a> Context<'a> { } } + /// Returns the acir value at the provided databus offset + fn get_from_call_data( + &mut self, + offset: &mut AcirVar, + call_data_block: BlockId, + typ: &Type, + ) -> Result { + match typ { + Type::Numeric(_) => self.array_get_value(&Type::field(), call_data_block, offset), + Type::Array(arc, len) => { + let mut result = Vector::new(); + for _i in 0..*len { + for sub_type in arc.iter() { + let element = self.get_from_call_data(offset, call_data_block, sub_type)?; + result.push_back(element); + } + } + Ok(AcirValue::Array(result)) + } + _ => unimplemented!("Unsupported type in databus"), + } + } + /// Generates a read opcode for the array /// `index_side_effect == false` means that we ensured `var_index` will have a type matching the value in the array fn array_get( @@ -1316,27 +1328,19 @@ impl<'a> Context<'a> { let block_id = self.ensure_array_is_initialized(array, dfg)?; let results = dfg.instruction_results(instruction); let res_typ = dfg.type_of_value(results[0]); - // Get operations to call-data parameters are replaced by a get to the call-data-bus array - if let Some(call_data) = - self.data_bus.call_data.iter().find(|cd| cd.index_map.contains_key(&array)) - { - let type_size = res_typ.flattened_size(); - let type_size = self.acir_context.add_constant(FieldElement::from(type_size as i128)); - let offset = self.acir_context.mul_var(var_index, type_size)?; + let call_data = + self.data_bus.call_data.iter().find(|cd| cd.index_map.contains_key(&array)).cloned(); + if let Some(call_data) = call_data { + let call_data_block = self.ensure_array_is_initialized(call_data.array_id, dfg)?; let bus_index = self .acir_context .add_constant(FieldElement::from(call_data.index_map[&array] as i128)); - let new_index = self.acir_context.add_var(offset, bus_index)?; - return self.array_get( - instruction, - call_data.array_id, - new_index, - dfg, - index_side_effect, - ); + let mut current_index = self.acir_context.add_var(bus_index, var_index)?; + let result = self.get_from_call_data(&mut current_index, call_data_block, &res_typ)?; + self.define_result(dfg, instruction, result.clone()); + return Ok(result); } - // Compiler sanity check assert!( !res_typ.contains_slice_element(), @@ -1441,7 +1445,7 @@ impl<'a> Context<'a> { // a separate SSA value and restrictions on slice indices should be generated elsewhere in the SSA. let array_typ = dfg.type_of_value(array); let array_len = if !array_typ.contains_slice_element() { - array_typ.flattened_size() + array_typ.flattened_size() as usize } else { self.flattened_slice_size(array, dfg) }; @@ -1532,11 +1536,11 @@ impl<'a> Context<'a> { if !already_initialized { let value = &dfg[array]; match value { - Value::Array { .. } | Value::Instruction { .. } => { + Value::Instruction { .. } => { let value = self.convert_value(array, dfg); let array_typ = dfg.type_of_value(array); let len = if !array_typ.contains_slice_element() { - array_typ.flattened_size() + array_typ.flattened_size() as usize } else { self.flattened_slice_size(array, dfg) }; @@ -1575,13 +1579,6 @@ impl<'a> Context<'a> { match array_typ { Type::Array(_, _) | Type::Slice(_) => { match &dfg[array_id] { - Value::Array { array, .. } => { - for (i, value) in array.iter().enumerate() { - flat_elem_type_sizes.push( - self.flattened_slice_size(*value, dfg) + flat_elem_type_sizes[i], - ); - } - } Value::Instruction { .. } | Value::Param { .. } => { // An instruction representing the slice means it has been processed previously during ACIR gen. // Use the previously defined result of an array operation to fetch the internal type information. @@ -1714,13 +1711,6 @@ impl<'a> Context<'a> { fn flattened_slice_size(&mut self, array_id: ValueId, dfg: &DataFlowGraph) -> usize { let mut size = 0; match &dfg[array_id] { - Value::Array { array, .. } => { - // The array is going to be the flattened outer array - // Flattened slice size from SSA value does not need to be multiplied by the len - for value in array { - size += self.flattened_slice_size(*value, dfg); - } - } Value::NumericConstant { .. } => { size += 1; } @@ -1821,7 +1811,7 @@ impl<'a> Context<'a> { return_values .iter() - .fold(0, |acc, value_id| acc + dfg.type_of_value(*value_id).flattened_size()) + .fold(0, |acc, value_id| acc + dfg.type_of_value(*value_id).flattened_size() as usize) } /// Converts an SSA terminator's return values into their ACIR representations @@ -1882,18 +1872,15 @@ impl<'a> Context<'a> { let acir_value = match value { Value::NumericConstant { constant, typ } => { - AcirValue::Var(self.acir_context.add_constant(*constant), typ.into()) - } - Value::Array { array, .. } => { - let elements = array.iter().map(|element| self.convert_value(*element, dfg)); - AcirValue::Array(elements.collect()) + let typ = AcirType::from(Type::Numeric(*typ)); + AcirValue::Var(self.acir_context.add_constant(*constant), typ) } Value::Intrinsic(..) => todo!(), Value::Function(function_id) => { // This conversion is for debugging support only, to allow the // debugging instrumentation code to work. Taking the reference // of a function in ACIR is useless. - let id = self.acir_context.add_constant(function_id.to_usize()); + let id = self.acir_context.add_constant(function_id.to_u32()); AcirValue::Var(id, AcirType::field()) } Value::ForeignFunction(_) => unimplemented!( @@ -1983,6 +1970,7 @@ impl<'a> Context<'a> { BinaryOp::Mod => self.acir_context.modulo_var( lhs, rhs, + binary_type.clone(), bit_count, self.current_side_effects_enabled_var, ), @@ -2145,6 +2133,15 @@ impl<'a> Context<'a> { result_ids: &[ValueId], ) -> Result, RuntimeError> { match intrinsic { + Intrinsic::Hint(Hint::BlackBox) => { + // Identity function; at the ACIR level this is a no-op, it only affects the SSA. + assert_eq!( + arguments.len(), + result_ids.len(), + "ICE: BlackBox input and output lengths should match." + ); + Ok(arguments.iter().map(|v| self.convert_value(*v, dfg)).collect()) + } Intrinsic::BlackBox(black_box) => { // Slices are represented as a tuple of (length, slice contents). // We must check the inputs to determine if there are slices @@ -2170,7 +2167,7 @@ impl<'a> Context<'a> { let inputs = vecmap(&arguments_no_slice_len, |arg| self.convert_value(*arg, dfg)); let output_count = result_ids.iter().fold(0usize, |sum, result_id| { - sum + dfg.try_get_array_length(*result_id).unwrap_or(1) + sum + dfg.try_get_array_length(*result_id).unwrap_or(1) as usize }); let vars = self.acir_context.black_box_function(black_box, inputs, output_count)?; @@ -2194,7 +2191,7 @@ impl<'a> Context<'a> { endian, field, radix, - array_length as u32, + array_length, result_type[0].clone().into(), ) .map(|array| vec![array]) @@ -2208,12 +2205,7 @@ impl<'a> Context<'a> { }; self.acir_context - .bit_decompose( - endian, - field, - array_length as u32, - result_type[0].clone().into(), - ) + .bit_decompose(endian, field, array_length, result_type[0].clone().into()) .map(|array| vec![array]) } Intrinsic::ArrayLen => { @@ -2234,7 +2226,7 @@ impl<'a> Context<'a> { let acir_value = self.convert_value(slice_contents, dfg); let array_len = if !slice_typ.contains_slice_element() { - slice_typ.flattened_size() + slice_typ.flattened_size() as usize } else { self.flattened_slice_size(slice_contents, dfg) }; @@ -2774,6 +2766,16 @@ impl<'a> Context<'a> { Intrinsic::DerivePedersenGenerators => { unreachable!("DerivePedersenGenerators can only be called with constants") } + Intrinsic::FieldLessThan => { + unreachable!("FieldLessThan can only be called in unconstrained") + } + Intrinsic::ArrayRefCount | Intrinsic::SliceRefCount => { + let zero = self.acir_context.add_constant(FieldElement::zero()); + Ok(vec![AcirValue::Var( + zero, + AcirType::NumericType(NumericType::Unsigned { bit_size: 32 }), + )]) + } } } @@ -2807,22 +2809,6 @@ impl<'a> Context<'a> { Ok(()) } - /// Given an array value, return the numerical type of its element. - /// Panics if the given value is not an array or has a non-numeric element type. - fn array_element_type(dfg: &DataFlowGraph, value: ValueId) -> AcirType { - match dfg.type_of_value(value) { - Type::Array(elements, _) => { - assert_eq!(elements.len(), 1); - (&elements[0]).into() - } - Type::Slice(elements) => { - assert_eq!(elements.len(), 1); - (&elements[0]).into() - } - _ => unreachable!("Expected array type"), - } - } - /// Convert a Vec into a Vec using the given result ids. /// If the type of a result id is an array, several acir vars are collected into /// a single AcirValue::Array of the same length. @@ -2907,25 +2893,30 @@ mod test { }, FieldElement, }; - use im::vector; use noirc_errors::Location; use noirc_frontend::monomorphization::ast::InlineType; use std::collections::BTreeMap; use crate::{ + acir::BrilligStdlibFunc, brillig::Brillig, ssa::{ - acir_gen::acir_ir::generated_acir::BrilligStdlibFunc, function_builder::FunctionBuilder, - ir::{function::FunctionId, instruction::BinaryOp, map::Id, types::Type}, + ir::{ + dfg::CallStack, + function::FunctionId, + instruction::BinaryOp, + map::Id, + types::{NumericType, Type}, + }, }, }; fn build_basic_foo_with_return( builder: &mut FunctionBuilder, foo_id: FunctionId, - // `InlineType` can only exist on ACIR functions, so if the option is `None` we should generate a Brillig function - inline_type: Option, + brillig: bool, + inline_type: InlineType, ) { // fn foo f1 { // b0(v0: Field, v1: Field): @@ -2933,19 +2924,21 @@ mod test { // constrain v2 == u1 0 // return v0 // } - if let Some(inline_type) = inline_type { - builder.new_function("foo".into(), foo_id, inline_type); + if brillig { + builder.new_brillig_function("foo".into(), foo_id, inline_type); } else { - builder.new_brillig_function("foo".into(), foo_id); + builder.new_function("foo".into(), foo_id, inline_type); } // Set a call stack for testing whether `brillig_locations` in the `GeneratedAcir` was accurately set. - builder.set_call_stack(vector![Location::dummy(), Location::dummy()]); + let mut stack = CallStack::unit(Location::dummy()); + stack.push_back(Location::dummy()); + builder.set_call_stack(stack); let foo_v0 = builder.add_parameter(Type::field()); let foo_v1 = builder.add_parameter(Type::field()); let foo_equality_check = builder.insert_binary(foo_v0, BinaryOp::Eq, foo_v1); - let zero = builder.numeric_constant(0u128, Type::unsigned(1)); + let zero = builder.numeric_constant(0u128, NumericType::unsigned(1)); builder.insert_constrain(foo_equality_check, zero, None); builder.terminate_with_return(vec![foo_v0]); } @@ -3000,9 +2993,9 @@ mod test { builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); builder.terminate_with_return(vec![]); - build_basic_foo_with_return(&mut builder, foo_id, Some(inline_type)); + build_basic_foo_with_return(&mut builder, foo_id, false, inline_type); - let ssa = builder.finish(); + let ssa = builder.finish().generate_entry_point_index(); let (acir_functions, _, _, _) = ssa .into_acir(&Brillig::default(), ExpressionWidth::default()) @@ -3105,11 +3098,12 @@ mod test { builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); builder.terminate_with_return(vec![]); - build_basic_foo_with_return(&mut builder, foo_id, Some(inline_type)); + build_basic_foo_with_return(&mut builder, foo_id, false, inline_type); let ssa = builder.finish(); let (acir_functions, _, _, _) = ssa + .generate_entry_point_index() .into_acir(&Brillig::default(), ExpressionWidth::default()) .expect("Should compile manually written SSA into ACIR"); // The expected result should look very similar to the above test expect that the input witnesses of the `Call` @@ -3205,9 +3199,9 @@ mod test { .to_vec(); builder.terminate_with_return(vec![foo_call[0]]); - build_basic_foo_with_return(&mut builder, foo_id, Some(inline_type)); + build_basic_foo_with_return(&mut builder, foo_id, false, inline_type); - let ssa = builder.finish(); + let ssa = builder.finish().generate_entry_point_index(); let (acir_functions, _, _, _) = ssa .into_acir(&Brillig::default(), ExpressionWidth::default()) @@ -3327,13 +3321,14 @@ mod test { builder.insert_call(bar, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); builder.terminate_with_return(vec![]); - build_basic_foo_with_return(&mut builder, foo_id, None); - build_basic_foo_with_return(&mut builder, bar_id, None); + build_basic_foo_with_return(&mut builder, foo_id, true, InlineType::default()); + build_basic_foo_with_return(&mut builder, bar_id, true, InlineType::default()); let ssa = builder.finish(); let brillig = ssa.to_brillig(false); let (acir_functions, brillig_functions, _, _) = ssa + .generate_entry_point_index() .into_acir(&brillig, ExpressionWidth::default()) .expect("Should compile manually written SSA into ACIR"); @@ -3387,7 +3382,7 @@ mod test { // Call the same primitive operation again let v1_div_v2 = builder.insert_binary(main_v1, BinaryOp::Div, main_v2); - let one = builder.numeric_constant(1u128, Type::unsigned(32)); + let one = builder.numeric_constant(1u128, NumericType::unsigned(32)); builder.insert_constrain(v1_div_v2, one, None); builder.terminate_with_return(vec![]); @@ -3398,6 +3393,7 @@ mod test { // The Brillig bytecode we insert for the stdlib is hardcoded so we do not need to provide any // Brillig artifacts to the ACIR gen pass. let (acir_functions, brillig_functions, _, _) = ssa + .generate_entry_point_index() .into_acir(&Brillig::default(), ExpressionWidth::default()) .expect("Should compile manually written SSA into ACIR"); @@ -3459,12 +3455,12 @@ mod test { // Call the same primitive operation again let v1_div_v2 = builder.insert_binary(main_v1, BinaryOp::Div, main_v2); - let one = builder.numeric_constant(1u128, Type::unsigned(32)); + let one = builder.numeric_constant(1u128, NumericType::unsigned(32)); builder.insert_constrain(v1_div_v2, one, None); builder.terminate_with_return(vec![]); - build_basic_foo_with_return(&mut builder, foo_id, None); + build_basic_foo_with_return(&mut builder, foo_id, true, InlineType::default()); let ssa = builder.finish(); // We need to generate Brillig artifacts for the regular Brillig function and pass them to the ACIR generation pass. @@ -3472,6 +3468,7 @@ mod test { println!("{}", ssa); let (acir_functions, brillig_functions, _, _) = ssa + .generate_entry_point_index() .into_acir(&brillig, ExpressionWidth::default()) .expect("Should compile manually written SSA into ACIR"); @@ -3544,15 +3541,15 @@ mod test { // Call the same primitive operation again let v1_div_v2 = builder.insert_binary(main_v1, BinaryOp::Div, main_v2); - let one = builder.numeric_constant(1u128, Type::unsigned(32)); + let one = builder.numeric_constant(1u128, NumericType::unsigned(32)); builder.insert_constrain(v1_div_v2, one, None); builder.terminate_with_return(vec![]); // Build a Brillig function - build_basic_foo_with_return(&mut builder, foo_id, None); + build_basic_foo_with_return(&mut builder, foo_id, true, InlineType::default()); // Build an ACIR function which has the same logic as the Brillig function above - build_basic_foo_with_return(&mut builder, bar_id, Some(InlineType::Fold)); + build_basic_foo_with_return(&mut builder, bar_id, false, InlineType::Fold); let ssa = builder.finish(); // We need to generate Brillig artifacts for the regular Brillig function and pass them to the ACIR generation pass. @@ -3560,6 +3557,7 @@ mod test { println!("{}", ssa); let (acir_functions, brillig_functions, _, _) = ssa + .generate_entry_point_index() .into_acir(&brillig, ExpressionWidth::default()) .expect("Should compile manually written SSA into ACIR"); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen.rs index 628ec9657f2..ca4e783aa93 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen.rs @@ -1,7 +1,6 @@ pub(crate) mod brillig_black_box; pub(crate) mod brillig_block; pub(crate) mod brillig_block_variables; -pub(crate) mod brillig_directive; pub(crate) mod brillig_fn; pub(crate) mod brillig_slice_ops; mod constant_allocation; @@ -10,11 +9,17 @@ mod variable_liveness; use acvm::FieldElement; use self::{brillig_block::BrilligBlock, brillig_fn::FunctionContext}; -use super::brillig_ir::{ - artifact::{BrilligArtifact, Label}, - BrilligContext, +use super::{ + brillig_ir::{ + artifact::{BrilligArtifact, BrilligParameter, GeneratedBrillig, Label}, + BrilligContext, + }, + Brillig, +}; +use crate::{ + errors::InternalError, + ssa::ir::{dfg::CallStack, function::Function}, }; -use crate::ssa::ir::function::Function; /// Converting an SSA function into Brillig bytecode. pub(crate) fn convert_ssa_function( @@ -27,6 +32,8 @@ pub(crate) fn convert_ssa_function( brillig_context.enter_context(Label::function(func.id())); + brillig_context.call_check_max_stack_depth_procedure(); + for block in function_context.blocks.clone() { BrilligBlock::compile(&mut function_context, &mut brillig_context, block, &func.dfg); } @@ -35,3 +42,43 @@ pub(crate) fn convert_ssa_function( artifact.name = func.name().to_string(); artifact } + +pub(crate) fn gen_brillig_for( + func: &Function, + arguments: Vec, + brillig: &Brillig, +) -> Result, InternalError> { + // Create the entry point artifact + let mut entry_point = BrilligContext::new_entry_point_artifact( + arguments, + FunctionContext::return_values(func), + func.id(), + ); + entry_point.name = func.name().to_string(); + + // Link the entry point with all dependencies + while let Some(unresolved_fn_label) = entry_point.first_unresolved_function_call() { + let artifact = &brillig.find_by_label(unresolved_fn_label.clone()); + let artifact = match artifact { + Some(artifact) => artifact, + None => { + return Err(InternalError::General { + message: format!("Cannot find linked fn {unresolved_fn_label}"), + call_stack: CallStack::new(), + }) + } + }; + entry_point.link_with(artifact); + // Insert the range of opcode locations occupied by a procedure + if let Some(procedure_id) = &artifact.procedure { + let num_opcodes = entry_point.byte_code.len(); + let previous_num_opcodes = entry_point.byte_code.len() - artifact.byte_code.len(); + // We subtract one as to keep the range inclusive on both ends + entry_point + .procedure_locations + .insert(procedure_id.clone(), (previous_num_opcodes, num_opcodes - 1)); + } + } + // Generate the final bytecode + Ok(entry_point.finish()) +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs index 889af07fbef..2ddcea26570 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs @@ -7,10 +7,8 @@ use acvm::{ }; use crate::brillig::brillig_ir::{ - brillig_variable::{BrilligVariable, SingleAddrVariable}, - debug_show::DebugToString, - registers::RegisterAllocator, - BrilligBinaryOp, BrilligContext, + brillig_variable::BrilligVariable, debug_show::DebugToString, registers::RegisterAllocator, + BrilligContext, }; /// Transforms SSA's black box function calls into the corresponding brillig instructions @@ -61,47 +59,23 @@ pub(crate) fn convert_black_box_call { + BlackBoxFunc::Keccakf1600 => { if let ( - [message, BrilligVariable::SingleAddr(message_size)], + [BrilligVariable::BrilligArray(input_array)], [BrilligVariable::BrilligArray(result_array)], ) = (function_arguments, function_results) { - let message_vector = convert_array_or_vector(brillig_context, *message, bb_func); - let output_heap_array = - brillig_context.codegen_brillig_array_to_heap_array(*result_array); - - // Message_size is not usize - brillig_context.cast_instruction( - SingleAddrVariable::new_usize(message_vector.size), - *message_size, - ); - - brillig_context.black_box_op_instruction(BlackBoxOp::Keccak256 { - message: message_vector, - output: output_heap_array, - }); - - brillig_context.deallocate_heap_vector(message_vector); - brillig_context.deallocate_heap_array(output_heap_array); - } else { - unreachable!("ICE: Keccak256 expects message, message size and result array") - } - } - BlackBoxFunc::Keccakf1600 => { - if let ([message], [BrilligVariable::BrilligArray(result_array)]) = - (function_arguments, function_results) - { - let message_vector = convert_array_or_vector(brillig_context, *message, bb_func); + let input_heap_array = + brillig_context.codegen_brillig_array_to_heap_array(*input_array); let output_heap_array = brillig_context.codegen_brillig_array_to_heap_array(*result_array); brillig_context.black_box_op_instruction(BlackBoxOp::Keccakf1600 { - message: message_vector, + input: input_heap_array, output: output_heap_array, }); - brillig_context.deallocate_heap_vector(message_vector); + brillig_context.deallocate_heap_array(input_heap_array); brillig_context.deallocate_heap_array(output_heap_array); } else { unreachable!("ICE: Keccakf1600 expects one array argument and one array result") @@ -170,63 +144,6 @@ pub(crate) fn convert_black_box_call { - if let ( - [message, BrilligVariable::SingleAddr(domain_separator)], - [BrilligVariable::BrilligArray(result_array)], - ) = (function_arguments, function_results) - { - let inputs = convert_array_or_vector(brillig_context, *message, bb_func); - let output = brillig_context.codegen_brillig_array_to_heap_array(*result_array); - brillig_context.black_box_op_instruction(BlackBoxOp::PedersenCommitment { - inputs, - domain_separator: domain_separator.address, - output, - }); - brillig_context.deallocate_heap_vector(inputs); - brillig_context.deallocate_heap_array(output); - } else { - unreachable!("ICE: Pedersen expects one array argument, a register for the domain separator, and one array result") - } - } - BlackBoxFunc::PedersenHash => { - if let ( - [message, BrilligVariable::SingleAddr(domain_separator)], - [BrilligVariable::SingleAddr(result)], - ) = (function_arguments, function_results) - { - let inputs = convert_array_or_vector(brillig_context, *message, bb_func); - brillig_context.black_box_op_instruction(BlackBoxOp::PedersenHash { - inputs, - domain_separator: domain_separator.address, - output: result.address, - }); - brillig_context.deallocate_heap_vector(inputs); - } else { - unreachable!("ICE: Pedersen hash expects one array argument, a register for the domain separator, and one register result") - } - } - BlackBoxFunc::SchnorrVerify => { - if let ( - [BrilligVariable::SingleAddr(public_key_x), BrilligVariable::SingleAddr(public_key_y), signature, message], - [BrilligVariable::SingleAddr(result_register)], - ) = (function_arguments, function_results) - { - let message = convert_array_or_vector(brillig_context, *message, bb_func); - let signature = convert_array_or_vector(brillig_context, *signature, bb_func); - brillig_context.black_box_op_instruction(BlackBoxOp::SchnorrVerify { - public_key_x: public_key_x.address, - public_key_y: public_key_y.address, - message, - signature, - result: result_register.address, - }); - brillig_context.deallocate_heap_vector(message); - brillig_context.deallocate_heap_vector(signature); - } else { - unreachable!("ICE: Schnorr verify expects two registers for the public key, an array for signature, an array for the message hash and one result register") - } - } BlackBoxFunc::MultiScalarMul => { if let ([points, scalars], [BrilligVariable::BrilligArray(outputs)]) = (function_arguments, function_results) @@ -413,21 +330,23 @@ pub(crate) fn convert_black_box_call { - if let ([message, hash_values], [BrilligVariable::BrilligArray(result_array)]) = - (function_arguments, function_results) + if let ( + [BrilligVariable::BrilligArray(input_array), BrilligVariable::BrilligArray(hash_values)], + [BrilligVariable::BrilligArray(result_array)], + ) = (function_arguments, function_results) { - let message_vector = convert_array_or_vector(brillig_context, *message, bb_func); - let hash_values = convert_array_or_vector(brillig_context, *hash_values, bb_func); + let input = brillig_context.codegen_brillig_array_to_heap_array(*input_array); + let hash_values = brillig_context.codegen_brillig_array_to_heap_array(*hash_values); let output = brillig_context.codegen_brillig_array_to_heap_array(*result_array); brillig_context.black_box_op_instruction(BlackBoxOp::Sha256Compression { - input: message_vector, + input, hash_values, output, }); - brillig_context.deallocate_heap_vector(message_vector); - brillig_context.deallocate_heap_vector(hash_values); + brillig_context.deallocate_heap_array(input); + brillig_context.deallocate_heap_array(hash_values); brillig_context.deallocate_heap_array(output); } else { unreachable!("ICE: Sha256Compression expects two array argument, one array result") @@ -455,19 +374,8 @@ pub(crate) fn convert_black_box_call BrilligBlock<'block> { ); } TerminatorInstruction::Return { return_values, .. } => { - let return_registers: Vec<_> = return_values - .iter() - .map(|value_id| { - let return_variable = self.convert_ssa_value(*value_id, dfg); - return_variable.extract_register() - }) - .collect(); + let return_registers = vecmap(return_values, |value_id| { + self.convert_ssa_value(*value_id, dfg).extract_register() + }); self.brillig_context.codegen_return(&return_registers); } } @@ -229,16 +226,14 @@ impl<'block> BrilligBlock<'block> { dfg.get_numeric_constant_with_type(*rhs), ) { // If the constraint is of the form `x == u1 1` then we can simply constrain `x` directly - ( - Some((constant, Type::Numeric(NumericType::Unsigned { bit_size: 1 }))), - None, - ) if constant == FieldElement::one() => { + (Some((constant, NumericType::Unsigned { bit_size: 1 })), None) + if constant == FieldElement::one() => + { (self.convert_ssa_single_addr_value(*rhs, dfg), false) } - ( - None, - Some((constant, Type::Numeric(NumericType::Unsigned { bit_size: 1 }))), - ) if constant == FieldElement::one() => { + (None, Some((constant, NumericType::Unsigned { bit_size: 1 }))) + if constant == FieldElement::one() => + { (self.convert_ssa_single_addr_value(*lhs, dfg), false) } @@ -259,7 +254,7 @@ impl<'block> BrilligBlock<'block> { }; match assert_message { - Some(ConstrainError::Dynamic(selector, values)) => { + Some(ConstrainError::Dynamic(selector, _, values)) => { let payload_values = vecmap(values, |value| self.convert_ssa_value(*value, dfg)); let payload_as_params = vecmap(values, |value| { @@ -270,7 +265,7 @@ impl<'block> BrilligBlock<'block> { condition, payload_values, payload_as_params, - selector.as_u64(), + *selector, ); } Some(ConstrainError::StaticString(message)) => { @@ -374,34 +369,10 @@ impl<'block> BrilligBlock<'block> { match output_register { // Returned vectors need to emit some bytecode to format the result as a BrilligVector ValueOrArray::HeapVector(heap_vector) => { - // Update the stack pointer so that we do not overwrite - // dynamic memory returned from other external calls - // Single values and allocation of fixed sized arrays has already been handled - // inside of `allocate_external_call_result` - let total_size = self.brillig_context.allocate_register(); - self.brillig_context.codegen_usize_op( - heap_vector.size, - total_size, - BrilligBinaryOp::Add, - 2, // RC and Length + self.brillig_context.initialize_externally_returned_vector( + output_variable.extract_vector(), + *heap_vector, ); - - self.brillig_context - .increase_free_memory_pointer_instruction(total_size); - let brillig_vector = output_variable.extract_vector(); - let size_pointer = self.brillig_context.allocate_register(); - - self.brillig_context.codegen_usize_op( - brillig_vector.pointer, - size_pointer, - BrilligBinaryOp::Add, - 1_usize, // Slices are [RC, Size, ...items] - ); - self.brillig_context - .store_instruction(size_pointer, heap_vector.size); - self.brillig_context.deallocate_register(size_pointer); - self.brillig_context.deallocate_register(total_size); - // Update the dynamic slice length maintained in SSA if let ValueOrArray::MemoryAddress(len_index) = output_values[i - 1] { @@ -429,183 +400,255 @@ impl<'block> BrilligBlock<'block> { let result_ids = dfg.instruction_results(instruction_id); self.convert_ssa_function_call(*func_id, arguments, dfg, result_ids); } - Value::Intrinsic(Intrinsic::BlackBox(bb_func)) => { - // Slices are represented as a tuple of (length, slice contents). - // We must check the inputs to determine if there are slices - // and make sure that we pass the correct inputs to the black box function call. - // The loop below only keeps the slice contents, so that - // setting up a black box function with slice inputs matches the expected - // number of arguments specified in the function signature. - let mut arguments_no_slice_len = Vec::new(); - for (i, arg) in arguments.iter().enumerate() { - if matches!(dfg.type_of_value(*arg), Type::Numeric(_)) { - if i < arguments.len() - 1 { - if !matches!(dfg.type_of_value(arguments[i + 1]), Type::Slice(_)) { - arguments_no_slice_len.push(*arg); - } + Value::Intrinsic(intrinsic) => { + // This match could be combined with the above but without it rust analyzer + // can't automatically insert any missing cases + match intrinsic { + Intrinsic::ArrayLen => { + let result_variable = self.variables.define_single_addr_variable( + self.function_context, + self.brillig_context, + dfg.instruction_results(instruction_id)[0], + dfg, + ); + let param_id = arguments[0]; + // Slices are represented as a tuple in the form: (length, slice contents). + // Thus, we can expect the first argument to a field in the case of a slice + // or an array in the case of an array. + if let Type::Numeric(_) = dfg.type_of_value(param_id) { + let len_variable = self.convert_ssa_value(arguments[0], dfg); + let length = len_variable.extract_single_addr(); + self.brillig_context + .mov_instruction(result_variable.address, length.address); } else { - arguments_no_slice_len.push(*arg); + self.convert_ssa_array_len( + arguments[0], + result_variable.address, + dfg, + ); } - } else { - arguments_no_slice_len.push(*arg); } - } - - let function_arguments = - vecmap(&arguments_no_slice_len, |arg| self.convert_ssa_value(*arg, dfg)); - let function_results = dfg.instruction_results(instruction_id); - let function_results = vecmap(function_results, |result| { - self.allocate_external_call_result(*result, dfg) - }); - convert_black_box_call( - self.brillig_context, - bb_func, - &function_arguments, - &function_results, - ); - } - Value::Intrinsic(Intrinsic::ArrayLen) => { - let result_variable = self.variables.define_single_addr_variable( - self.function_context, - self.brillig_context, - dfg.instruction_results(instruction_id)[0], - dfg, - ); - let param_id = arguments[0]; - // Slices are represented as a tuple in the form: (length, slice contents). - // Thus, we can expect the first argument to a field in the case of a slice - // or an array in the case of an array. - if let Type::Numeric(_) = dfg.type_of_value(param_id) { - let len_variable = self.convert_ssa_value(arguments[0], dfg); - let length = len_variable.extract_single_addr(); - self.brillig_context - .mov_instruction(result_variable.address, length.address); - } else { - self.convert_ssa_array_len(arguments[0], result_variable.address, dfg); - } - } - Value::Intrinsic(Intrinsic::AsSlice) => { - let source_variable = self.convert_ssa_value(arguments[0], dfg); - let result_ids = dfg.instruction_results(instruction_id); - let destination_len_variable = self.variables.define_single_addr_variable( - self.function_context, - self.brillig_context, - result_ids[0], - dfg, - ); - let destination_variable = self.variables.define_variable( - self.function_context, - self.brillig_context, - result_ids[1], - dfg, - ); - let destination_vector = destination_variable.extract_vector(); - let source_array = source_variable.extract_array(); - let element_size = dfg.type_of_value(arguments[0]).element_size(); - - let source_size_register = self - .brillig_context - .make_usize_constant_instruction(source_array.size.into()); - - // we need to explicitly set the destination_len_variable - self.brillig_context.codegen_usize_op( - source_size_register.address, - destination_len_variable.address, - BrilligBinaryOp::UnsignedDiv, - element_size, - ); + Intrinsic::AsSlice => { + let source_variable = self.convert_ssa_value(arguments[0], dfg); + let result_ids = dfg.instruction_results(instruction_id); + let destination_len_variable = + self.variables.define_single_addr_variable( + self.function_context, + self.brillig_context, + result_ids[0], + dfg, + ); + let destination_variable = self.variables.define_variable( + self.function_context, + self.brillig_context, + result_ids[1], + dfg, + ); + let destination_vector = destination_variable.extract_vector(); + let source_array = source_variable.extract_array(); + let element_size = dfg.type_of_value(arguments[0]).element_size(); - self.brillig_context - .codegen_initialize_vector(destination_vector, source_size_register); - - // Items - let vector_items_pointer = - self.brillig_context.codegen_make_vector_items_pointer(destination_vector); - let array_items_pointer = - self.brillig_context.codegen_make_array_items_pointer(source_array); - - self.brillig_context.codegen_mem_copy( - array_items_pointer, - vector_items_pointer, - source_size_register, - ); + let source_size_register = self + .brillig_context + .make_usize_constant_instruction(source_array.size.into()); + + // we need to explicitly set the destination_len_variable + self.brillig_context.codegen_usize_op( + source_size_register.address, + destination_len_variable.address, + BrilligBinaryOp::UnsignedDiv, + element_size, + ); - self.brillig_context.deallocate_single_addr(source_size_register); - self.brillig_context.deallocate_register(vector_items_pointer); - self.brillig_context.deallocate_register(array_items_pointer); - } - Value::Intrinsic( - Intrinsic::SlicePushBack - | Intrinsic::SlicePopBack - | Intrinsic::SlicePushFront - | Intrinsic::SlicePopFront - | Intrinsic::SliceInsert - | Intrinsic::SliceRemove, - ) => { - self.convert_ssa_slice_intrinsic_call( - dfg, - &dfg[dfg.resolve(*func)], - instruction_id, - arguments, - ); - } - Value::Intrinsic(Intrinsic::ToRadix(endianness)) => { - let results = dfg.instruction_results(instruction_id); - - let source = self.convert_ssa_single_addr_value(arguments[0], dfg); - let radix = self.convert_ssa_single_addr_value(arguments[1], dfg); - - let target_array = self - .variables - .define_variable( - self.function_context, - self.brillig_context, - results[0], - dfg, - ) - .extract_array(); - - self.brillig_context.codegen_to_radix( - source, - target_array, - radix, - matches!(endianness, Endian::Big), - false, - ); - } - Value::Intrinsic(Intrinsic::ToBits(endianness)) => { - let results = dfg.instruction_results(instruction_id); + self.brillig_context.codegen_initialize_vector( + destination_vector, + source_size_register, + None, + ); - let source = self.convert_ssa_single_addr_value(arguments[0], dfg); + // Items + let vector_items_pointer = self + .brillig_context + .codegen_make_vector_items_pointer(destination_vector); + let array_items_pointer = + self.brillig_context.codegen_make_array_items_pointer(source_array); + + self.brillig_context.codegen_mem_copy( + array_items_pointer, + vector_items_pointer, + source_size_register, + ); - let target_array = self - .variables - .define_variable( - self.function_context, - self.brillig_context, - results[0], - dfg, - ) - .extract_array(); + self.brillig_context.deallocate_single_addr(source_size_register); + self.brillig_context.deallocate_register(vector_items_pointer); + self.brillig_context.deallocate_register(array_items_pointer); + } + Intrinsic::SlicePushBack + | Intrinsic::SlicePopBack + | Intrinsic::SlicePushFront + | Intrinsic::SlicePopFront + | Intrinsic::SliceInsert + | Intrinsic::SliceRemove => { + self.convert_ssa_slice_intrinsic_call( + dfg, + &dfg[dfg.resolve(*func)], + instruction_id, + arguments, + ); + } + Intrinsic::ToBits(endianness) => { + let results = dfg.instruction_results(instruction_id); + + let source = self.convert_ssa_single_addr_value(arguments[0], dfg); + + let target_array = self + .variables + .define_variable( + self.function_context, + self.brillig_context, + results[0], + dfg, + ) + .extract_array(); + + let two = self + .brillig_context + .make_usize_constant_instruction(2_usize.into()); + + self.brillig_context.codegen_to_radix( + source, + target_array, + two, + matches!(endianness, Endian::Little), + true, + ); - let two = self.brillig_context.make_usize_constant_instruction(2_usize.into()); + self.brillig_context.deallocate_single_addr(two); + } - self.brillig_context.codegen_to_radix( - source, - target_array, - two, - matches!(endianness, Endian::Big), - true, - ); + Intrinsic::ToRadix(endianness) => { + let results = dfg.instruction_results(instruction_id); + + let source = self.convert_ssa_single_addr_value(arguments[0], dfg); + let radix = self.convert_ssa_single_addr_value(arguments[1], dfg); + + let target_array = self + .variables + .define_variable( + self.function_context, + self.brillig_context, + results[0], + dfg, + ) + .extract_array(); + + self.brillig_context.codegen_to_radix( + source, + target_array, + radix, + matches!(endianness, Endian::Little), + false, + ); + } + Intrinsic::Hint(Hint::BlackBox) => { + let result_ids = dfg.instruction_results(instruction_id); + self.convert_ssa_identity_call(arguments, dfg, result_ids); + } + Intrinsic::BlackBox(bb_func) => { + // Slices are represented as a tuple of (length, slice contents). + // We must check the inputs to determine if there are slices + // and make sure that we pass the correct inputs to the black box function call. + // The loop below only keeps the slice contents, so that + // setting up a black box function with slice inputs matches the expected + // number of arguments specified in the function signature. + let mut arguments_no_slice_len = Vec::new(); + for (i, arg) in arguments.iter().enumerate() { + if matches!(dfg.type_of_value(*arg), Type::Numeric(_)) { + if i < arguments.len() - 1 { + if !matches!( + dfg.type_of_value(arguments[i + 1]), + Type::Slice(_) + ) { + arguments_no_slice_len.push(*arg); + } + } else { + arguments_no_slice_len.push(*arg); + } + } else { + arguments_no_slice_len.push(*arg); + } + } - self.brillig_context.deallocate_single_addr(two); + let function_arguments = vecmap(&arguments_no_slice_len, |arg| { + self.convert_ssa_value(*arg, dfg) + }); + let function_results = dfg.instruction_results(instruction_id); + let function_results = vecmap(function_results, |result| { + self.allocate_external_call_result(*result, dfg) + }); + convert_black_box_call( + self.brillig_context, + bb_func, + &function_arguments, + &function_results, + ); + } + // `Intrinsic::AsWitness` is used to provide hints to acir-gen on optimal expression splitting. + // It is then useless in the brillig runtime and so we can ignore it + Intrinsic::AsWitness => (), + Intrinsic::FieldLessThan => { + let lhs = self.convert_ssa_single_addr_value(arguments[0], dfg); + assert!(lhs.bit_size == FieldElement::max_num_bits()); + let rhs = self.convert_ssa_single_addr_value(arguments[1], dfg); + assert!(rhs.bit_size == FieldElement::max_num_bits()); + + let results = dfg.instruction_results(instruction_id); + let destination = self + .variables + .define_variable( + self.function_context, + self.brillig_context, + results[0], + dfg, + ) + .extract_single_addr(); + assert!(destination.bit_size == 1); + + self.brillig_context.binary_instruction( + lhs, + rhs, + destination, + BrilligBinaryOp::LessThan, + ); + } + Intrinsic::ArrayRefCount | Intrinsic::SliceRefCount => { + let array = self.convert_ssa_value(arguments[0], dfg); + let result = dfg.instruction_results(instruction_id)[0]; + + let destination = self.variables.define_variable( + self.function_context, + self.brillig_context, + result, + dfg, + ); + let destination = destination.extract_register(); + let array = array.extract_register(); + self.brillig_context.load_instruction(destination, array); + } + Intrinsic::FromField + | Intrinsic::AsField + | Intrinsic::IsUnconstrained + | Intrinsic::DerivePedersenGenerators + | Intrinsic::ApplyRangeConstraint + | Intrinsic::StrAsBytes + | Intrinsic::AssertConstant + | Intrinsic::StaticAssert + | Intrinsic::ArrayAsStrUnchecked => { + unreachable!("unsupported function call type {:?}", dfg[*func]) + } + } } - - // `Intrinsic::AsWitness` is used to provide hints to acir-gen on optimal expression splitting. - // It is then useless in the brillig runtime and so we can ignore it - Value::Intrinsic(Intrinsic::AsWitness) => (), - - _ => { + Value::Instruction { .. } | Value::Param { .. } | Value::NumericConstant { .. } => { unreachable!("unsupported function call type {:?}", dfg[*func]) } }, @@ -759,6 +802,43 @@ impl<'block> BrilligBlock<'block> { Instruction::IfElse { .. } => { unreachable!("IfElse instructions should not be possible in brillig") } + Instruction::MakeArray { elements: array, typ } => { + let value_id = dfg.instruction_results(instruction_id)[0]; + if !self.variables.is_allocated(&value_id) { + let new_variable = self.variables.define_variable( + self.function_context, + self.brillig_context, + value_id, + dfg, + ); + + // Initialize the variable + match new_variable { + BrilligVariable::BrilligArray(brillig_array) => { + self.brillig_context.codegen_initialize_array(brillig_array); + } + BrilligVariable::BrilligVector(vector) => { + let size = self + .brillig_context + .make_usize_constant_instruction(array.len().into()); + self.brillig_context.codegen_initialize_vector(vector, size, None); + self.brillig_context.deallocate_single_addr(size); + } + _ => unreachable!( + "ICE: Cannot initialize array value created as {new_variable:?}" + ), + }; + + // Write the items + let items_pointer = self + .brillig_context + .codegen_make_array_or_vector_items_pointer(new_variable); + + self.initialize_constant_array(array, typ, dfg, items_pointer); + + self.brillig_context.deallocate_register(items_pointer); + } + } }; let dead_variables = self @@ -783,26 +863,9 @@ impl<'block> BrilligBlock<'block> { dfg: &DataFlowGraph, result_ids: &[ValueId], ) { - // Convert the arguments to registers casting those to the types of the receiving function - let argument_registers: Vec = arguments - .iter() - .map(|argument_id| self.convert_ssa_value(*argument_id, dfg).extract_register()) - .collect(); - - let variables_to_save = self.variables.get_available_variables(self.function_context); - - let saved_registers = self - .brillig_context - .codegen_pre_call_save_registers_prep_args(&argument_registers, &variables_to_save); - - // Call instruction, which will interpret above registers 0..num args - self.brillig_context.add_external_call_instruction(func_id); - - // Important: resolve after pre_call_save_registers_prep_args - // This ensures we don't save the results to registers unnecessarily. - - // Allocate the registers for the variables where we are assigning the returns - let variables_assigned_to = vecmap(result_ids, |result_id| { + let argument_variables = + vecmap(arguments, |argument_id| self.convert_ssa_value(*argument_id, dfg)); + let return_variables = vecmap(result_ids, |result_id| { self.variables.define_variable( self.function_context, self.brillig_context, @@ -810,26 +873,31 @@ impl<'block> BrilligBlock<'block> { dfg, ) }); + self.brillig_context.codegen_call(func_id, &argument_variables, &return_variables); + } - // Collect the registers that should have been returned - let returned_registers: Vec = variables_assigned_to - .iter() - .map(|returned_variable| returned_variable.extract_register()) - .collect(); - - assert!( - !saved_registers.iter().any(|x| returned_registers.contains(x)), - "should not save registers used as function results" - ); + /// Copy the input arguments to the results. + fn convert_ssa_identity_call( + &mut self, + arguments: &[ValueId], + dfg: &DataFlowGraph, + result_ids: &[ValueId], + ) { + let argument_variables = + vecmap(arguments, |argument_id| self.convert_ssa_value(*argument_id, dfg)); - // puts the returns into the returned_registers and restores saved_registers - self.brillig_context - .codegen_post_call_prep_returns_load_registers(&returned_registers, &saved_registers); + let return_variables = vecmap(result_ids, |result_id| { + self.variables.define_variable( + self.function_context, + self.brillig_context, + *result_id, + dfg, + ) + }); - // Reset the register state to the one needed to hold the current available variables - let variables = self.variables.get_available_variables(self.function_context); - let registers = variables.into_iter().map(|variable| variable.extract_register()).collect(); - self.brillig_context.set_allocated_registers(registers); + for (src, dst) in argument_variables.into_iter().zip(return_variables) { + self.brillig_context.mov_instruction(dst.extract_register(), src.extract_register()); + } } fn validate_array_index( @@ -1215,8 +1283,8 @@ impl<'block> BrilligBlock<'block> { result_variable: SingleAddrVariable, ) { let binary_type = type_of_binary_operation( - dfg[binary.lhs].get_type(), - dfg[binary.rhs].get_type(), + dfg[binary.lhs].get_type().as_ref(), + dfg[binary.rhs].get_type().as_ref(), binary.operator, ); @@ -1235,7 +1303,7 @@ impl<'block> BrilligBlock<'block> { let brillig_binary_op = match binary.operator { BinaryOp::Div => { if is_signed { - self.convert_signed_division(left, right, result_variable); + self.brillig_context.convert_signed_division(left, right, result_variable); return; } else if is_field { BrilligBinaryOp::FieldDiv @@ -1267,7 +1335,14 @@ impl<'block> BrilligBlock<'block> { BinaryOp::Or => BrilligBinaryOp::Or, BinaryOp::Xor => BrilligBinaryOp::Xor, BinaryOp::Shl => BrilligBinaryOp::Shl, - BinaryOp::Shr => BrilligBinaryOp::Shr, + BinaryOp::Shr => { + if is_signed { + self.convert_signed_shr(left, right, result_variable); + return; + } else { + BrilligBinaryOp::Shr + } + } }; self.brillig_context.binary_instruction(left, right, result_variable, brillig_binary_op); @@ -1283,97 +1358,6 @@ impl<'block> BrilligBlock<'block> { ); } - /// Splits a two's complement signed integer in the sign bit and the absolute value. - /// For example, -6 i8 (11111010) is split to 00000110 (6, absolute value) and 1 (is_negative). - fn absolute_value( - &mut self, - num: SingleAddrVariable, - absolute_value: SingleAddrVariable, - result_is_negative: SingleAddrVariable, - ) { - let max_positive = self - .brillig_context - .make_constant_instruction(((1_u128 << (num.bit_size - 1)) - 1).into(), num.bit_size); - - // Compute if num is negative - self.brillig_context.binary_instruction( - max_positive, - num, - result_is_negative, - BrilligBinaryOp::LessThan, - ); - - // Two's complement of num - let zero = self.brillig_context.make_constant_instruction(0_usize.into(), num.bit_size); - let twos_complement = - SingleAddrVariable::new(self.brillig_context.allocate_register(), num.bit_size); - self.brillig_context.binary_instruction(zero, num, twos_complement, BrilligBinaryOp::Sub); - - // absolute_value = result_is_negative ? twos_complement : num - self.brillig_context.conditional_mov_instruction( - absolute_value.address, - result_is_negative.address, - twos_complement.address, - num.address, - ); - - self.brillig_context.deallocate_single_addr(zero); - self.brillig_context.deallocate_single_addr(max_positive); - self.brillig_context.deallocate_single_addr(twos_complement); - } - - fn convert_signed_division( - &mut self, - left: SingleAddrVariable, - right: SingleAddrVariable, - result: SingleAddrVariable, - ) { - let left_is_negative = SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); - let left_abs_value = - SingleAddrVariable::new(self.brillig_context.allocate_register(), left.bit_size); - - let right_is_negative = - SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); - let right_abs_value = - SingleAddrVariable::new(self.brillig_context.allocate_register(), right.bit_size); - - let result_is_negative = - SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); - - // Compute both absolute values - self.absolute_value(left, left_abs_value, left_is_negative); - self.absolute_value(right, right_abs_value, right_is_negative); - - // Perform the division on the absolute values - self.brillig_context.binary_instruction( - left_abs_value, - right_abs_value, - result, - BrilligBinaryOp::UnsignedDiv, - ); - - // Compute result sign - self.brillig_context.binary_instruction( - left_is_negative, - right_is_negative, - result_is_negative, - BrilligBinaryOp::Xor, - ); - - // If result has to be negative, perform two's complement - self.brillig_context.codegen_if(result_is_negative.address, |ctx| { - let zero = ctx.make_constant_instruction(0_usize.into(), result.bit_size); - ctx.binary_instruction(zero, result, result, BrilligBinaryOp::Sub); - ctx.deallocate_single_addr(zero); - }); - - self.brillig_context.deallocate_single_addr(left_is_negative); - self.brillig_context.deallocate_single_addr(left_abs_value); - self.brillig_context.deallocate_single_addr(right_is_negative); - self.brillig_context.deallocate_single_addr(right_abs_value); - self.brillig_context.deallocate_single_addr(result_is_negative); - } - fn convert_signed_modulo( &mut self, left: SingleAddrVariable, @@ -1386,7 +1370,7 @@ impl<'block> BrilligBlock<'block> { SingleAddrVariable::new(self.brillig_context.allocate_register(), left.bit_size); // i = left / right - self.convert_signed_division(left, right, scratch_var_i); + self.brillig_context.convert_signed_division(left, right, scratch_var_i); // j = i * right self.brillig_context.binary_instruction( @@ -1433,6 +1417,56 @@ impl<'block> BrilligBlock<'block> { self.brillig_context.deallocate_single_addr(bias); } + fn convert_signed_shr( + &mut self, + left: SingleAddrVariable, + right: SingleAddrVariable, + result: SingleAddrVariable, + ) { + // Check if left is negative + let left_is_negative = SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); + let max_positive = self + .brillig_context + .make_constant_instruction(((1_u128 << (left.bit_size - 1)) - 1).into(), left.bit_size); + self.brillig_context.binary_instruction( + max_positive, + left, + left_is_negative, + BrilligBinaryOp::LessThan, + ); + + self.brillig_context.codegen_branch(left_is_negative.address, |ctx, is_negative| { + if is_negative { + let one = ctx.make_constant_instruction(1_u128.into(), left.bit_size); + + // computes 2^right + let two = ctx.make_constant_instruction(2_u128.into(), left.bit_size); + let two_pow = ctx.make_constant_instruction(1_u128.into(), left.bit_size); + let right_u32 = SingleAddrVariable::new(ctx.allocate_register(), 32); + ctx.cast(right_u32, right); + let pow_body = |ctx: &mut BrilligContext<_, _>, _: SingleAddrVariable| { + ctx.binary_instruction(two_pow, two, two_pow, BrilligBinaryOp::Mul); + }; + ctx.codegen_for_loop(None, right_u32.address, None, pow_body); + + // Right shift using division on 1-complement + ctx.binary_instruction(left, one, result, BrilligBinaryOp::Add); + ctx.convert_signed_division(result, two_pow, result); + ctx.binary_instruction(result, one, result, BrilligBinaryOp::Sub); + + // Clean-up + ctx.deallocate_single_addr(one); + ctx.deallocate_single_addr(two); + ctx.deallocate_single_addr(two_pow); + ctx.deallocate_single_addr(right_u32); + } else { + ctx.binary_instruction(left, right, result, BrilligBinaryOp::Shr); + } + }); + + self.brillig_context.deallocate_single_addr(left_is_negative); + } + #[allow(clippy::too_many_arguments)] fn add_overflow_check( &mut self, @@ -1566,46 +1600,6 @@ impl<'block> BrilligBlock<'block> { new_variable } } - Value::Array { array, typ } => { - if self.variables.is_allocated(&value_id) { - self.variables.get_allocation(self.function_context, value_id, dfg) - } else { - let new_variable = self.variables.define_variable( - self.function_context, - self.brillig_context, - value_id, - dfg, - ); - - // Initialize the variable - match new_variable { - BrilligVariable::BrilligArray(brillig_array) => { - self.brillig_context.codegen_initialize_array(brillig_array); - } - BrilligVariable::BrilligVector(vector) => { - let size = self - .brillig_context - .make_usize_constant_instruction(array.len().into()); - self.brillig_context.codegen_initialize_vector(vector, size); - self.brillig_context.deallocate_single_addr(size); - } - _ => unreachable!( - "ICE: Cannot initialize array value created as {new_variable:?}" - ), - }; - - // Write the items - let items_pointer = self - .brillig_context - .codegen_make_array_or_vector_items_pointer(new_variable); - - self.initialize_constant_array(array, typ, dfg, items_pointer); - - self.brillig_context.deallocate_register(items_pointer); - - new_variable - } - } Value::Function(_) => { // For the debugger instrumentation we want to allow passing // around values representing function pointers, even though @@ -1620,7 +1614,7 @@ impl<'block> BrilligBlock<'block> { self.brillig_context.const_instruction( new_variable.extract_single_addr(), - value_id.to_usize().into(), + value_id.to_u32().into(), ); new_variable } @@ -1799,7 +1793,7 @@ impl<'block> BrilligBlock<'block> { dfg: &DataFlowGraph, ) -> BrilligVariable { let typ = dfg[result].get_type(); - match typ { + match typ.as_ref() { Type::Numeric(_) => self.variables.define_variable( self.function_context, self.brillig_context, @@ -1815,7 +1809,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); let array = variable.extract_array(); - self.allocate_foreign_call_result_array(typ, array); + self.allocate_foreign_call_result_array(typ.as_ref(), array); variable } @@ -1832,11 +1826,6 @@ impl<'block> BrilligBlock<'block> { // The stack pointer will then be updated by the caller of this method // once the external call is resolved and the array size is known self.brillig_context.load_free_memory_pointer_instruction(vector.pointer); - self.brillig_context.indirect_const_instruction( - vector.pointer, - BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, - 1_usize.into(), - ); variable } @@ -1860,7 +1849,7 @@ impl<'block> BrilligBlock<'block> { Type::Array(_, nested_size) => { let inner_array = BrilligArray { pointer: self.brillig_context.allocate_register(), - size: *nested_size, + size: *nested_size as usize, }; self.allocate_foreign_call_result_array(element_type, inner_array); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs index 393d4c967c2..bf0a1bc7347 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs @@ -142,7 +142,7 @@ pub(crate) fn allocate_value( } Type::Array(item_typ, elem_count) => BrilligVariable::BrilligArray(BrilligArray { pointer: brillig_context.allocate_register(), - size: compute_array_length(&item_typ, elem_count), + size: compute_array_length(&item_typ, elem_count as usize), }), Type::Slice(_) => BrilligVariable::BrilligVector(BrilligVector { pointer: brillig_context.allocate_register(), diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs deleted file mode 100644 index faf4242a9ca..00000000000 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs +++ /dev/null @@ -1,139 +0,0 @@ -use acvm::acir::{ - brillig::{BinaryFieldOp, BitSize, IntegerBitSize, MemoryAddress, Opcode as BrilligOpcode}, - AcirField, -}; - -use crate::brillig::brillig_ir::artifact::GeneratedBrillig; - -/// Generates brillig bytecode which computes the inverse of its input if not null, and zero else. -pub(crate) fn directive_invert() -> GeneratedBrillig { - // We generate the following code: - // fn invert(x : Field) -> Field { - // 1/ x - // } - - // The input argument, ie the value that will be inverted. - // We store the result in this register too. - let input = MemoryAddress::from(0); - let one_const = MemoryAddress::from(1); - let zero_const = MemoryAddress::from(2); - let input_is_zero = MemoryAddress::from(3); - // Location of the stop opcode - let stop_location = 8; - - GeneratedBrillig { - byte_code: vec![ - 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, - value: F::from(0_usize), - bit_size: BitSize::Field, - }, - BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Equals, - lhs: input, - rhs: zero_const, - destination: input_is_zero, - }, - // If the input is zero, then we jump to the stop opcode - BrilligOpcode::JumpIf { condition: input_is_zero, location: stop_location }, - // Put value one in register (1) - BrilligOpcode::Const { - destination: one_const, - value: F::one(), - bit_size: BitSize::Field, - }, - // Divide 1 by the input, and set the result of the division into register (0) - BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Div, - lhs: one_const, - rhs: input, - destination: input, - }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 1 }, - ], - assert_messages: Default::default(), - locations: Default::default(), - name: "directive_invert".to_string(), - } -} - -/// Generates brillig bytecode which computes `a / b` and returns the quotient and remainder. -/// -/// This is equivalent to the Noir (pseudo)code -/// -/// ```text -/// fn quotient(a: T, b: T) -> (T,T) { -/// (a/b, a-a/b*b) -/// } -/// ``` -pub(crate) fn directive_quotient() -> GeneratedBrillig { - // `a` is (0) (i.e register index 0) - // `b` is (1) - - 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_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) - BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::IntegerDiv, // We want integer division, not field division! - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(2), - }, - //(1)= q*b - BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Mul, - lhs: MemoryAddress::from(2), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(1), - }, - //(1) = a-q*b - BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Sub, - lhs: MemoryAddress::from(0), - rhs: MemoryAddress::from(1), - destination: MemoryAddress::from(1), - }, - //(0) = q - BrilligOpcode::Mov { - destination: MemoryAddress::from(0), - source: MemoryAddress::from(2), - }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 2 }, - ], - assert_messages: Default::default(), - locations: Default::default(), - name: "directive_integer_quotient".to_string(), - } -} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs index 2779be103cd..3dea7b3e7f5 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs @@ -59,7 +59,7 @@ impl FunctionContext { vecmap(item_type.iter(), |item_typ| { FunctionContext::ssa_type_to_parameter(item_typ) }), - *size, + *size as usize, ), Type::Slice(_) => { panic!("ICE: Slice parameters cannot be derived from type information") diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index 85db1bd8b96..26c7151bf07 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -79,17 +79,15 @@ impl<'block> BrilligBlock<'block> { source_vector: BrilligVector, removed_items: &[BrilligVariable], ) { - let read_pointer = self.brillig_context.allocate_register(); - self.brillig_context.call_vector_pop_procedure( + let read_pointer = self.brillig_context.codegen_make_vector_items_pointer(source_vector); + self.read_variables(read_pointer, removed_items); + self.brillig_context.deallocate_register(read_pointer); + + self.brillig_context.call_vector_pop_front_procedure( source_vector, target_vector, - read_pointer, removed_items.len(), - false, ); - - self.read_variables(read_pointer, removed_items); - self.brillig_context.deallocate_register(read_pointer); } pub(crate) fn slice_pop_back_operation( @@ -99,12 +97,11 @@ impl<'block> BrilligBlock<'block> { removed_items: &[BrilligVariable], ) { let read_pointer = self.brillig_context.allocate_register(); - self.brillig_context.call_vector_pop_procedure( + self.brillig_context.call_vector_pop_back_procedure( source_vector, target_vector, read_pointer, removed_items.len(), - true, ); self.read_variables(read_pointer, removed_items); @@ -162,6 +159,7 @@ mod tests { use std::vec; use acvm::FieldElement; + use noirc_frontend::monomorphization::ast::InlineType; use crate::brillig::brillig_gen::brillig_block::BrilligBlock; use crate::brillig::brillig_gen::brillig_block_variables::BlockVariables; @@ -182,7 +180,7 @@ mod tests { fn create_test_environment() -> (Ssa, FunctionContext, BrilligContext) { let mut builder = FunctionBuilder::new("main".to_string(), Id::test_new(0)); - builder.set_runtime(RuntimeType::Brillig); + builder.set_runtime(RuntimeType::Brillig(InlineType::default())); let ssa = builder.finish(); let mut brillig_context = create_context(ssa.main_id); @@ -212,7 +210,7 @@ mod tests { push_back: bool, array: Vec, item_to_push: FieldElement, - mut expected_return: Vec, + expected_return: Vec, ) { let arguments = vec![ BrilligParameter::Slice( @@ -222,11 +220,15 @@ mod tests { BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; let result_length = array.len() + 1; + assert_eq!(result_length, expected_return.len()); + let result_length_with_metadata = result_length + 2; // Leading length and capacity + + // Entry points don't support returning slices, so we implicitly cast the vector to an array + // With the metadata at the start. let returns = vec![BrilligParameter::Array( vec![BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], - result_length + 1, // Leading length since the we return a vector + result_length_with_metadata, )]; - expected_return.insert(0, FieldElement::from(result_length)); let (_, mut function_context, mut context) = create_test_environment(); @@ -261,14 +263,17 @@ mod tests { let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let (vm, return_data_offset, return_data_size) = create_and_run_vm(array.into_iter().chain(vec![item_to_push]).collect(), &bytecode); - assert_eq!(return_data_size, expected_return.len()); - assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] - .iter() - .map(|mem_val| mem_val.to_field()) - .collect::>(), - expected_return - ); + assert_eq!(return_data_size, result_length_with_metadata); + let mut returned_vector: Vec = vm.get_memory() + [return_data_offset..(return_data_offset + result_length_with_metadata)] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect(); + let returned_size = returned_vector.remove(0); + assert_eq!(returned_size, result_length.into()); + let _returned_capacity = returned_vector.remove(0); + + assert_eq!(returned_vector, expected_return); } test_case_push( @@ -320,7 +325,7 @@ mod tests { fn test_case_pop( pop_back: bool, array: Vec, - mut expected_return_array: Vec, + expected_return_array: Vec, expected_return_item: FieldElement, ) { let arguments = vec![BrilligParameter::Slice( @@ -328,15 +333,18 @@ mod tests { array.len(), )]; let result_length = array.len() - 1; + assert_eq!(result_length, expected_return_array.len()); + let result_length_with_metadata = result_length + 2; // Leading length and capacity + // Entry points don't support returning slices, so we implicitly cast the vector to an array + // With the metadata at the start. let returns = vec![ + BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), BrilligParameter::Array( vec![BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], - result_length + 1, + result_length_with_metadata, ), - BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; - expected_return_array.insert(0, FieldElement::from(result_length)); let (_, mut function_context, mut context) = create_test_environment(); @@ -366,22 +374,28 @@ mod tests { ); } - context.codegen_return(&[target_vector.pointer, removed_item.address]); + context.codegen_return(&[removed_item.address, target_vector.pointer]); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; - let expected_return: Vec<_> = - expected_return_array.into_iter().chain(vec![expected_return_item]).collect(); + let (vm, return_data_offset, return_data_size) = create_and_run_vm(array.clone(), &bytecode); - assert_eq!(return_data_size, expected_return.len()); - - assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] - .iter() - .map(|mem_val| mem_val.to_field()) - .collect::>(), - expected_return - ); + // vector + removed item + assert_eq!(return_data_size, result_length_with_metadata + 1); + + let mut return_data: Vec = vm.get_memory() + [return_data_offset..(return_data_offset + return_data_size)] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect(); + let returned_item = return_data.remove(0); + assert_eq!(returned_item, expected_return_item); + + let returned_size = return_data.remove(0); + assert_eq!(returned_size, result_length.into()); + let _returned_capacity = return_data.remove(0); + + assert_eq!(return_data, expected_return_array); } test_case_pop( @@ -413,7 +427,7 @@ mod tests { array: Vec, item: FieldElement, index: FieldElement, - mut expected_return: Vec, + expected_return: Vec, ) { let arguments = vec![ BrilligParameter::Slice( @@ -424,11 +438,15 @@ mod tests { BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; let result_length = array.len() + 1; + assert_eq!(result_length, expected_return.len()); + let result_length_with_metadata = result_length + 2; // Leading length and capacity + + // Entry points don't support returning slices, so we implicitly cast the vector to an array + // With the metadata at the start. let returns = vec![BrilligParameter::Array( vec![BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], - result_length + 1, + result_length_with_metadata, )]; - expected_return.insert(0, FieldElement::from(result_length)); let (_, mut function_context, mut context) = create_test_environment(); @@ -460,15 +478,18 @@ mod tests { let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let (vm, return_data_offset, return_data_size) = create_and_run_vm(calldata, &bytecode); - assert_eq!(return_data_size, expected_return.len()); - - assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] - .iter() - .map(|mem_val| mem_val.to_field()) - .collect::>(), - expected_return - ); + assert_eq!(return_data_size, result_length_with_metadata); + + let mut returned_vector: Vec = vm.get_memory() + [return_data_offset..(return_data_offset + result_length_with_metadata)] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect(); + let returned_size = returned_vector.remove(0); + assert_eq!(returned_size, result_length.into()); + let _returned_capacity = returned_vector.remove(0); + + assert_eq!(returned_vector, expected_return); } test_case_insert( @@ -545,7 +566,7 @@ mod tests { fn test_case_remove( array: Vec, index: FieldElement, - mut expected_array: Vec, + expected_array: Vec, expected_removed_item: FieldElement, ) { let arguments = vec![ @@ -556,15 +577,16 @@ mod tests { BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; let result_length = array.len() - 1; + assert_eq!(result_length, expected_array.len()); + let result_length_with_metadata = result_length + 2; // Leading length and capacity let returns = vec![ + BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), BrilligParameter::Array( vec![BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE)], - result_length + 1, + result_length_with_metadata, ), - BrilligParameter::SingleAddr(BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ]; - expected_array.insert(0, FieldElement::from(result_length)); let (_, mut function_context, mut context) = create_test_environment(); @@ -591,24 +613,29 @@ mod tests { &[BrilligVariable::SingleAddr(removed_item)], ); - context.codegen_return(&[target_vector.pointer, removed_item.address]); + context.codegen_return(&[removed_item.address, target_vector.pointer]); let calldata: Vec<_> = array.into_iter().chain(vec![index]).collect(); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let (vm, return_data_offset, return_data_size) = create_and_run_vm(calldata, &bytecode); - let expected_return: Vec<_> = - expected_array.into_iter().chain(vec![expected_removed_item]).collect(); - assert_eq!(return_data_size, expected_return.len()); + // vector + removed item + assert_eq!(return_data_size, result_length_with_metadata + 1); - assert_eq!( - vm.get_memory()[return_data_offset..(return_data_offset + expected_return.len())] - .iter() - .map(|mem_val| mem_val.to_field()) - .collect::>(), - expected_return - ); + let mut return_data: Vec = vm.get_memory() + [return_data_offset..(return_data_offset + return_data_size)] + .iter() + .map(|mem_val| mem_val.to_field()) + .collect(); + let returned_item = return_data.remove(0); + assert_eq!(returned_item, expected_removed_item); + + let returned_size = return_data.remove(0); + assert_eq!(returned_size, result_length.into()); + let _returned_capacity = return_data.remove(0); + + assert_eq!(return_data, expected_array); } test_case_remove( diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/constant_allocation.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/constant_allocation.rs index f9ded224b33..61ca20be2f5 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/constant_allocation.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/constant_allocation.rs @@ -89,8 +89,7 @@ impl ConstantAllocation { } if let Some(terminator_instruction) = block.terminator() { terminator_instruction.for_each_value(|value_id| { - let variables = collect_variables_of_value(value_id, &func.dfg); - for variable in variables { + if let Some(variable) = collect_variables_of_value(value_id, &func.dfg) { record_if_constant(block_id, variable, InstructionLocation::Terminator); } }); @@ -166,7 +165,7 @@ impl ConstantAllocation { } pub(crate) fn is_constant_value(id: ValueId, dfg: &DataFlowGraph) -> bool { - matches!(&dfg[dfg.resolve(id)], Value::NumericConstant { .. } | Value::Array { .. }) + matches!(&dfg[dfg.resolve(id)], Value::NumericConstant { .. }) } /// For a given function, finds all the blocks that are within loops diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs index 92595292bf0..d6851a9ecf9 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs @@ -45,32 +45,19 @@ fn find_back_edges( } /// Collects the underlying variables inside a value id. It might be more than one, for example in constant arrays that are constructed with multiple vars. -pub(crate) fn collect_variables_of_value(value_id: ValueId, dfg: &DataFlowGraph) -> Vec { +pub(crate) fn collect_variables_of_value( + value_id: ValueId, + dfg: &DataFlowGraph, +) -> Option { let value_id = dfg.resolve(value_id); let value = &dfg[value_id]; match value { - Value::Instruction { .. } | Value::Param { .. } => { - vec![value_id] - } - // Literal arrays are constants, but might use variable values to initialize. - Value::Array { array, .. } => { - let mut value_ids = vec![value_id]; - - array.iter().for_each(|item_id| { - let underlying_ids = collect_variables_of_value(*item_id, dfg); - value_ids.extend(underlying_ids); - }); - - value_ids - } - Value::NumericConstant { .. } => { - vec![value_id] + Value::Instruction { .. } | Value::Param { .. } | Value::NumericConstant { .. } => { + Some(value_id) } // Functions are not variables in a defunctionalized SSA. Only constant function values should appear. - Value::ForeignFunction(_) | Value::Function(_) | Value::Intrinsic(..) => { - vec![] - } + Value::ForeignFunction(_) | Value::Function(_) | Value::Intrinsic(..) => None, } } @@ -341,6 +328,7 @@ impl VariableLiveness { #[cfg(test)] mod test { use fxhash::FxHashSet; + use noirc_frontend::monomorphization::ast::InlineType; use crate::brillig::brillig_gen::constant_allocation::ConstantAllocation; use crate::brillig::brillig_gen::variable_liveness::VariableLiveness; @@ -373,7 +361,7 @@ mod test { let main_id = Id::test_new(1); let mut builder = FunctionBuilder::new("main".into(), main_id); - builder.set_runtime(RuntimeType::Brillig); + builder.set_runtime(RuntimeType::Brillig(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -384,7 +372,7 @@ mod test { let v3 = builder.insert_allocate(Type::field()); - let zero = builder.numeric_constant(0u128, Type::field()); + let zero = builder.field_constant(0u128); builder.insert_store(v3, zero); let v4 = builder.insert_binary(v0, BinaryOp::Eq, zero); @@ -393,7 +381,7 @@ mod test { builder.switch_to_block(b2); - let twenty_seven = builder.numeric_constant(27u128, Type::field()); + let twenty_seven = builder.field_constant(27u128); let v7 = builder.insert_binary(v0, BinaryOp::Add, twenty_seven); builder.insert_store(v3, v7); @@ -483,7 +471,7 @@ mod test { let main_id = Id::test_new(1); let mut builder = FunctionBuilder::new("main".into(), main_id); - builder.set_runtime(RuntimeType::Brillig); + builder.set_runtime(RuntimeType::Brillig(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -499,7 +487,7 @@ mod test { let v3 = builder.insert_allocate(Type::field()); - let zero = builder.numeric_constant(0u128, Type::field()); + let zero = builder.field_constant(0u128); builder.insert_store(v3, zero); builder.terminate_with_jmp(b1, vec![zero]); @@ -527,7 +515,7 @@ mod test { builder.switch_to_block(b5); - let twenty_seven = builder.numeric_constant(27u128, Type::field()); + let twenty_seven = builder.field_constant(27u128); let v10 = builder.insert_binary(v7, BinaryOp::Eq, twenty_seven); let v11 = builder.insert_not(v10); @@ -546,7 +534,7 @@ mod test { builder.switch_to_block(b8); - let one = builder.numeric_constant(1u128, Type::field()); + let one = builder.field_constant(1u128); let v15 = builder.insert_binary(v7, BinaryOp::Add, one); builder.terminate_with_jmp(b4, vec![v15]); @@ -622,7 +610,7 @@ mod test { let main_id = Id::test_new(1); let mut builder = FunctionBuilder::new("main".into(), main_id); - builder.set_runtime(RuntimeType::Brillig); + builder.set_runtime(RuntimeType::Brillig(InlineType::default())); let v0 = builder.add_parameter(Type::bool()); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index d8065294b0c..8d5f14cee94 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -25,6 +25,7 @@ mod entry_point; mod instructions; use artifact::Label; +use brillig_variable::SingleAddrVariable; pub(crate) use instructions::BrilligBinaryOp; use registers::{RegisterAllocator, ScratchSpace}; @@ -36,6 +37,8 @@ use acvm::{ }; use debug_show::DebugShow; +use super::ProcedureId; + /// The Brillig VM does not apply a limit to the memory address space, /// As a convention, we take use 32 bits. This means that we assume that /// memory has 2^32 memory slots. @@ -43,19 +46,17 @@ pub(crate) const BRILLIG_MEMORY_ADDRESSING_BIT_SIZE: u32 = 32; // Registers reserved in runtime for special purposes. pub(crate) enum ReservedRegisters { + /// This register stores the stack pointer. All relative memory addresses are relative to this pointer. + StackPointer = 0, /// This register stores the free memory pointer. Allocations must be done after this pointer. - FreeMemoryPointer = 0, - /// This register stores the previous stack pointer. The registers of the caller are stored here. - PreviousStackPointer = 1, + FreeMemoryPointer = 1, /// This register stores a 1_usize constant. UsizeOne = 2, } impl ReservedRegisters { - /// The number of reserved registers. - /// - /// This is used to offset the general registers - /// which should not overwrite the special register + /// The number of reserved registers. These are allocated in the first memory positions. + /// The stack should start after the reserved registers. const NUM_RESERVED_REGISTERS: usize = 3; /// Returns the length of the reserved registers @@ -63,19 +64,16 @@ impl ReservedRegisters { Self::NUM_RESERVED_REGISTERS } - /// Returns the free memory pointer register. This will get used to allocate memory in runtime. - pub(crate) fn free_memory_pointer() -> MemoryAddress { - MemoryAddress::from(ReservedRegisters::FreeMemoryPointer as usize) + pub(crate) fn stack_pointer() -> MemoryAddress { + MemoryAddress::direct(ReservedRegisters::StackPointer as usize) } - /// Returns the previous stack pointer register. This will be used to restore the registers after a fn call. - pub(crate) fn previous_stack_pointer() -> MemoryAddress { - MemoryAddress::from(ReservedRegisters::PreviousStackPointer as usize) + pub(crate) fn free_memory_pointer() -> MemoryAddress { + MemoryAddress::direct(ReservedRegisters::FreeMemoryPointer as usize) } - /// Returns the usize one register. This will be used to perform arithmetic operations. pub(crate) fn usize_one() -> MemoryAddress { - MemoryAddress::from(ReservedRegisters::UsizeOne as usize) + MemoryAddress::direct(ReservedRegisters::UsizeOne as usize) } } @@ -112,13 +110,99 @@ impl BrilligContext { can_call_procedures: true, } } + + /// Splits a two's complement signed integer in the sign bit and the absolute value. + /// For example, -6 i8 (11111010) is split to 00000110 (6, absolute value) and 1 (is_negative). + pub(crate) fn absolute_value( + &mut self, + num: SingleAddrVariable, + absolute_value: SingleAddrVariable, + result_is_negative: SingleAddrVariable, + ) { + let max_positive = self + .make_constant_instruction(((1_u128 << (num.bit_size - 1)) - 1).into(), num.bit_size); + + // Compute if num is negative + self.binary_instruction(max_positive, num, result_is_negative, BrilligBinaryOp::LessThan); + + // Two's complement of num + let zero = self.make_constant_instruction(0_usize.into(), num.bit_size); + let twos_complement = SingleAddrVariable::new(self.allocate_register(), num.bit_size); + self.binary_instruction(zero, num, twos_complement, BrilligBinaryOp::Sub); + + // absolute_value = result_is_negative ? twos_complement : num + self.codegen_branch(result_is_negative.address, |ctx, is_negative| { + if is_negative { + ctx.mov_instruction(absolute_value.address, twos_complement.address); + } else { + ctx.mov_instruction(absolute_value.address, num.address); + } + }); + + self.deallocate_single_addr(zero); + self.deallocate_single_addr(max_positive); + self.deallocate_single_addr(twos_complement); + } + + pub(crate) fn convert_signed_division( + &mut self, + left: SingleAddrVariable, + right: SingleAddrVariable, + result: SingleAddrVariable, + ) { + let left_is_negative = SingleAddrVariable::new(self.allocate_register(), 1); + let left_abs_value = SingleAddrVariable::new(self.allocate_register(), left.bit_size); + + let right_is_negative = SingleAddrVariable::new(self.allocate_register(), 1); + let right_abs_value = SingleAddrVariable::new(self.allocate_register(), right.bit_size); + + let result_is_negative = SingleAddrVariable::new(self.allocate_register(), 1); + + // Compute both absolute values + self.absolute_value(left, left_abs_value, left_is_negative); + self.absolute_value(right, right_abs_value, right_is_negative); + + // Perform the division on the absolute values + self.binary_instruction( + left_abs_value, + right_abs_value, + result, + BrilligBinaryOp::UnsignedDiv, + ); + + // Compute result sign + self.binary_instruction( + left_is_negative, + right_is_negative, + result_is_negative, + BrilligBinaryOp::Xor, + ); + + // If result has to be negative, perform two's complement + self.codegen_if(result_is_negative.address, |ctx| { + let zero = ctx.make_constant_instruction(0_usize.into(), result.bit_size); + ctx.binary_instruction(zero, result, result, BrilligBinaryOp::Sub); + ctx.deallocate_single_addr(zero); + }); + + self.deallocate_single_addr(left_is_negative); + self.deallocate_single_addr(left_abs_value); + self.deallocate_single_addr(right_is_negative); + self.deallocate_single_addr(right_abs_value); + self.deallocate_single_addr(result_is_negative); + } } /// Special brillig context to codegen compiler intrinsic shared procedures impl BrilligContext { - pub(crate) fn new_for_procedure(enable_debug_trace: bool) -> BrilligContext { + pub(crate) fn new_for_procedure( + enable_debug_trace: bool, + procedure_id: ProcedureId, + ) -> BrilligContext { + let mut obj = BrilligArtifact::default(); + obj.procedure = Some(procedure_id); BrilligContext { - obj: BrilligArtifact::default(), + obj, registers: ScratchSpace::new(), context_label: Label::entrypoint(), current_section: 0, @@ -151,8 +235,8 @@ pub(crate) mod tests { use std::vec; use acvm::acir::brillig::{ - BitSize, ForeignCallParam, ForeignCallResult, HeapArray, HeapVector, IntegerBitSize, - MemoryAddress, ValueOrArray, + BitSize, ForeignCallParam, ForeignCallResult, HeapVector, IntegerBitSize, MemoryAddress, + ValueOrArray, }; use acvm::brillig_vm::brillig::HeapValueType; use acvm::brillig_vm::{VMStatus, VM}; @@ -169,29 +253,6 @@ pub(crate) mod tests { pub(crate) struct DummyBlackBoxSolver; impl BlackBoxFunctionSolver for DummyBlackBoxSolver { - fn schnorr_verify( - &self, - _public_key_x: &FieldElement, - _public_key_y: &FieldElement, - _signature: &[u8; 64], - _message: &[u8], - ) -> Result { - Ok(true) - } - fn pedersen_commitment( - &self, - _inputs: &[FieldElement], - _domain_separator: u32, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Ok((2_u128.into(), 3_u128.into())) - } - fn pedersen_hash( - &self, - _inputs: &[FieldElement], - _domain_separator: u32, - ) -> Result { - Ok(6_u128.into()) - } fn multi_scalar_mul( &self, _points: &[FieldElement], @@ -252,7 +313,8 @@ pub(crate) mod tests { calldata: Vec, bytecode: &[BrilligOpcode], ) -> (VM<'_, FieldElement, DummyBlackBoxSolver>, usize, usize) { - let mut vm = VM::new(calldata, bytecode, vec![], &DummyBlackBoxSolver); + let profiling_active = false; + let mut vm = VM::new(calldata, bytecode, vec![], &DummyBlackBoxSolver, profiling_active); let status = vm.process_opcodes(); if let VMStatus::Finished { return_data_offset, return_data_size } = status { @@ -279,10 +341,10 @@ pub(crate) mod tests { let r_stack = ReservedRegisters::free_memory_pointer(); // Start stack pointer at 0 context.usize_const_instruction(r_stack, FieldElement::from(ReservedRegisters::len() + 3)); - let r_input_size = MemoryAddress::from(ReservedRegisters::len()); - let r_array_ptr = MemoryAddress::from(ReservedRegisters::len() + 1); - let r_output_size = MemoryAddress::from(ReservedRegisters::len() + 2); - let r_equality = MemoryAddress::from(ReservedRegisters::len() + 3); + let r_input_size = MemoryAddress::direct(ReservedRegisters::len()); + let r_array_ptr = MemoryAddress::direct(ReservedRegisters::len() + 1); + let r_output_size = MemoryAddress::direct(ReservedRegisters::len() + 2); + let r_equality = MemoryAddress::direct(ReservedRegisters::len() + 3); context.usize_const_instruction(r_input_size, FieldElement::from(12_usize)); // copy our stack frame to r_array_ptr context.mov_instruction(r_array_ptr, r_stack); @@ -307,10 +369,23 @@ pub(crate) mod tests { // We push a JumpIf and Trap opcode directly as the constrain instruction // uses unresolved jumps which requires a block to be constructed in SSA and // we don't need this for Brillig IR tests - context.push_opcode(BrilligOpcode::JumpIf { condition: r_equality, location: 8 }); - context.push_opcode(BrilligOpcode::Trap { revert_data: HeapArray::default() }); + context.push_opcode(BrilligOpcode::Const { + destination: MemoryAddress::direct(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }); + context.push_opcode(BrilligOpcode::JumpIf { condition: r_equality, location: 9 }); + context.push_opcode(BrilligOpcode::Trap { + revert_data: HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(0), + }, + }); - context.stop_instruction(); + context.stop_instruction(HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(0), + }); let bytecode: Vec> = context.artifact().finish().byte_code; let number_sequence: Vec = @@ -320,6 +395,7 @@ pub(crate) mod tests { &bytecode, vec![ForeignCallResult { values: vec![ForeignCallParam::Array(number_sequence)] }], &DummyBlackBoxSolver, + false, ); let status = vm.process_opcodes(); assert_eq!(status, VMStatus::Finished { return_data_offset: 0, return_data_size: 0 }); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index d0bd91e185c..0e5b72c0b85 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -1,8 +1,11 @@ use acvm::acir::brillig::Opcode as BrilligOpcode; +use acvm::acir::circuit::ErrorSelector; use std::collections::{BTreeMap, HashMap}; -use crate::brillig::brillig_ir::procedures::ProcedureId; use crate::ssa::ir::{basic_block::BasicBlockId, dfg::CallStack, function::FunctionId}; +use crate::ErrorType; + +use super::procedures::ProcedureId; /// Represents a parameter or a return value of an entry point function. #[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] @@ -22,8 +25,9 @@ pub(crate) enum BrilligParameter { pub(crate) struct GeneratedBrillig { pub(crate) byte_code: Vec>, pub(crate) locations: BTreeMap, - pub(crate) assert_messages: BTreeMap, + pub(crate) error_types: BTreeMap, pub(crate) name: String, + pub(crate) procedure_locations: HashMap, } #[derive(Default, Debug, Clone)] @@ -31,10 +35,7 @@ pub(crate) struct GeneratedBrillig { /// It includes the bytecode of the function and all the metadata that allows linking with other functions. pub(crate) struct BrilligArtifact { pub(crate) byte_code: Vec>, - /// A map of bytecode positions to assertion messages. - /// Some error messages (compiler intrinsics) are not emitted via revert data, - /// instead, they are handled externally so they don't add size to user programs. - pub(crate) assert_messages: BTreeMap, + pub(crate) error_types: BTreeMap, /// The set of jumps that need to have their locations /// resolved. unresolved_jumps: Vec<(JumpInstructionPosition, UnresolvedJumpLocation)>, @@ -53,12 +54,20 @@ pub(crate) struct BrilligArtifact { call_stack: CallStack, /// Name of the function, only used for debugging purposes. pub(crate) name: String, + + /// This field contains the given procedure id if this artifact originates from as procedure + pub(crate) procedure: Option, + /// Procedure ID mapped to the range of its opcode locations + /// This is created as artifacts are linked together and allows us to determine + /// which opcodes originate from reusable procedures.s + /// The range is inclusive for both start and end opcode locations. + pub(crate) procedure_locations: HashMap, } /// A pointer to a location in the opcode. pub(crate) type OpcodeLocation = usize; -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Hash)] pub(crate) enum LabelType { /// Labels for the entry point bytecode Entrypoint, @@ -88,7 +97,7 @@ impl std::fmt::Display for LabelType { /// /// It is assumed that an entity will keep a map /// of labels to Opcode locations. -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Hash)] pub(crate) struct Label { pub(crate) label_type: LabelType, pub(crate) section: Option, @@ -96,7 +105,7 @@ pub(crate) struct Label { impl Label { pub(crate) fn add_section(&self, section: usize) -> Self { - Label { label_type: self.label_type, section: Some(section) } + Label { label_type: self.label_type.clone(), section: Some(section) } } pub(crate) fn function(func_id: FunctionId) -> Self { @@ -147,14 +156,15 @@ impl BrilligArtifact { GeneratedBrillig { byte_code: self.byte_code, locations: self.locations, - assert_messages: self.assert_messages, + error_types: self.error_types, name: self.name, + procedure_locations: self.procedure_locations, } } /// Gets the first unresolved function call of this artifact. pub(crate) fn first_unresolved_function_call(&self) -> Option